New Features For The New Year

on December 30th, 2007 at 5:19pm , , 3 responses

In a good timing for the new year, I'm happy to announce new features to AspView.

I have dedicated a post for each so I'd have a way to reference those features, and for my dear readers to comment on each feature.

So, what's all the fuss about?

  1. Nested layouts
    http://kenegozi.com/Blog/2007/12/30/nested-layouts.aspx
  2. New syntax for html encoded output
    http://kenegozi.com/Blog/2007/12/30/html-encoded-output-in-view-templates.aspx
  3. Embedded script blocks inside a view
    http://kenegozi.com/Blog/2007/12/30/embedded-script-blocks.aspx
  4. Layouts from custom locations
    http://kenegozi.com/Blog/2007/12/30/using-layout-from-a-custom-location.aspx
  5. Not throwing on null-ref in <%= %> blocks
    http://kenegozi.com/Blog/2007/12/30/no-more-null-ref-(almost).aspx

Downloads, as always, are from www.aspview.com

Nested Layouts

on December 30th, 2007 at 5:16pm , , 2 responses

A cool feature, repeatedly asked for by users (of AspView, and of MonoRail in general).

 

When stating the layout name in the controller, you use a comma separated list of layouts to be applied, from the most general (outer) inward.

 

Example:

in the controller:

[Layout("Site, Admin")]
public class UsersController : SmartDispatcherController
{
    public void Index() { }
}

and given those schematic templates:

  • (layouts\site.aspx):
    SiteLayout
  • (layouts\admin.aspx)
    AdminLayout
  • (users\index.aspx)
    Index  

We'd get:

rendered view

Embedded Script Blocks

on December 30th, 2007 at 5:16pm , , 1 responses

Say  you want to have the possibility to create a method to work in views.

for the sake of argument, let it be:

public string DoubleId(string s)
{
    return s + s;
}

your options:

  1. Create a Helper class and put it there
  2. Create a base class and put it there

But what if it's simple enough (so you won't need a unit-test) and it's not supposed to be reused (so creating a Helper/Base class is an overkill)?

Now you can put it directly in your view template, and this is how:

<script runat="server">
public string DoubleId(string s)
{
    return s + s;
}
</script>

Regular view code
<%=DoubleIt(view.Name) %>

 

Now the devil advocates would say that "Logic In View Is Evil". And I would concur. But it's not actually logic. It's supposed to be used for view-related string manipulations and such. And anyway you can do Evil Deeds without it, too. And you don't HAVE to use it if you don't want to.

 

The idea (and 99% of implementation) is by Gauthier Segay. Thanks dude !

Using Layout From a Custom Location

on December 30th, 2007 at 5:16pm , , 0 responses

It's been asked on the Castle mailing list, and was implemented for NVelocity (and for Brail too, I think), so now it works on AspView, too.

 

So, doing:

[Layout("\custom\layout")] 
public class MyController ...

Would use the template from Views\Custom\Layout.aspx

Html Encoded Output In View Templates

on December 30th, 2007 at 5:16pm , , 2 responses

The existing <%= %> syntax would keep output the raw strings, so it can be used to output properties that has markup inside, like CMS data, the ViewContents in layouts, CaptureFor data, etc.

 

If you want http encoded output, use <%# %> or ${} instead.

 

Example:

Given the following view template:

<%
string markup = "<span>";
%>

<%=markup%>
<%#markup%>
${markup}

 

The rendered output would be:

<span>
&lt;span&gt;
&lt;span&gt;

 

Have fun.

No More Null Ref (almost)

on December 30th, 2007 at 5:16pm , , 0 responses

I found out that on many occasions I use stuff like:

<aspview:properties>
string message = "";
</aspview:properties>

To avoid the need of:

<% = message ?? "" %>

 

That's it.

From now on, null values would just be ignored.

 

Notice that it won't help you on

<%=post.Blog.Title %> if post.Blog is null ...

YUI ColorPicker Within a non-posting Floating Dialog

on December 29th, 2007 at 8:40am 1 responses

My personal preference in javascript framework is prototype + YUI.

I take the language enhancements of prototype (enumerable/array, extend, $/$$), and the richness of widgets and event handling of YUI. One might say that prototype is my Javascript2, and YUI is the BCL.

 

These days I'm with YUI 2.4.1 and prototype 1.6.0

 

This week I needed to put floating color pickers on a few screens in a system.

Usually, the easiest thing would be to copy a pre-existing demo fro YUI docs. However, the color picker in dialog demo there was about the dialog posting to the server it's results, while I needed just to save the value into form fields.

 

The sample also uses a preexisting markup, which was not good in this scenario.

 

Plus, since the said system have a very complicated (and fragile) styling and scripts happening on many pages, strange things have happened to the dialog if ran more than once on the same page, so I've added a "destroy" method that would cause the dialog to be rebuilt each time. It's lightning fast, and has no visible effects on the user experience.

 

Another major change I've made to the sample, is the use of methods on a 'global' static object (CP) instead creating an instance of a function() and add the methods there (like the guys at YUI likes). The latter is nice in it's increased encapsulation, however the need to deal with the scoping issues is making event registration and event handlers too awkward imo.

 

Anyway - that's the code, you can use it as you will. Just remember it's "as-is", "no-warrenty" BSD thing.

 

YAHOO.ColorPicker = {};

// alias
var CP = YAHOO.ColorPicker;
CP.dialog = null;

 

// creates the dialog with a color picker inside
CP.createPicker = function() {
    CP.dialog = new YAHOO.widget.Dialog("yui-picker-panel", {
        width                : '500px',
        close                : false,
        fixedcenter          : true,
        visible              : false,
        draggable            : false,
        modal                : true,
        constraintoviewport  : true,
        effect               : {
            effect               : YAHOO.widget.ContainerEffect.FADE,
            duration             : 0.2
        },
        buttons              : [    
            { text:"Done",   handler:this.handleOk, isDefault:true },
            { text:"Cancel", handler:this.handleCancel }
        ]
    });

 

// dialog markup:
    CP.dialog.setHeader('Pick a color:');

// placeholder for the color picker
    CP.dialog.setBody('<div id="yui-picker" class="yui-picker"></div>');
    CP.dialog.render(document.body);
    $(CP.dialog.element).addClassName('yui-picker-panel');

 

// create the picker
    CP.picker = new YAHOO.widget.ColorPicker("yui-picker", {
        showhexcontrols   : true,
        showhexsummary    : false,
        images            : {
            PICKER_THUMB  : "/common/javascript/yui/colorpicker/assets/picker_thumb.png",
            HUE_THUMB        : "/common/javascript/yui/colorpicker/assets/hue_thumb.png"
        }
    });
}

 

// in here I have used prototype to get the hex data. you can of course use

// YUI's getElementsByClassName, jQuery, or your own method.
CP.handleOk = function() {
    var hexField = $(CP.dialog.element).down('.yui-picker-hex');
    var hex = hexField.value;
    $(CP.targetId).value = '#' + hex;
    CP.dialog.hide();
    setTimeout(CP.destroy, 300);
}

 

// removes the dialog completely
CP.destroy = function() {
    CP.dialog.destroy();
    CP.dialog = null;
}

 

CP.handleCancel = function() {

    CP.dialog.cancel();
    setTimeout(CP.destroy, 300);

}

 

// create the picker if needed, set it's value, and show

 

 

CP.showPicker = function(ev) {
    if (CP.dialog === null) {
        CP.createPicker();
    }
    var target = ev.target || ev.srcElement;
    CP.targetId = target.id;
    var val = target.value;
    if (val.match(/#?[a-fA-F0-9]{6}/)) {
        if (val.indexOf('#') === 0 && val.length > 1)
            val = val.substring(1);
        CP.picker.setValue(YAHOO.util.Color.hex2rgb(val));
    }
    CP.dialog.show();
}

 

// registering the pickers on our color fields
YAHOO.util.Event.onDOMReady(function() {
    var fields = YAHOO.util.Dom.getElementsByClassName('color-picked');
    YAHOO.util.Event.on(fields, "click", CP.showPicker);
});

 

You can try to clean the CP.destroy method and see if it works for your scenario.

 

hmm, ofcourse, needed YUI files are:

  • utilities/utilities.js
  • container/container-min.js
  • slider/slider-min.js
  • yui/colorpicker/colorpicker-beta.js
  • fonts/fonts-min.css
  • container/assets/container.css
  • container/assets/skins/sam/container.css
  • colorpicker/assets/skins/sam/colorpicker.css

Reaching 200 - a Useless Stat That Makes Me Proud

on December 21st, 2007 at 10:30am 3 responses

When I've started using feedburner (mid Sep.) there were about 160 subscribers.

Nowadays:

200 readers

 

Next to super-blogers like Scott Hanselman or even local blog heros like Ayende, its nothing.

But it's mine.

 

I can also see a very (obvious) correlation between the amount of code posts per month and the growth in popularity.

 

That mean that people likes reading code samples, and that they find it useful, so I'd do my best to make more of these, should time permit.

XSS, HttpEncode, AspView and being Secure By Default

on December 21st, 2007 at 9:21am , , , 21 responses

If you know not what XSS is or how easily you can expose your application to XSS, take a short read at the next posts:

AspView was written by me, for my (and my employer at the time) use. Therefore, I did not make it 'secure by default' in terms of HttpEncode.

 

However, seeing now that the convention lean toward outputing HtmlEncode-ed by default, I'm adapting AspView to that.

 

The usage would be similar to the one suggested for Asp.NET MVC at http://blog.codeville.net/2007/12/19/aspnet-mvc-prevent-xss-with-automatic-html-encoding/

 

So,

<%="<tag>" %> 

would output

&lt;tag&gt;

 

While

<%=RawHtml("<tag>") %>

would output

<tag>

 

The only exception here is ViewContents on layouts. since the view contents is 99% of the times made of markup, so in the layout would still write:

<%=ViewContents %> 

 

All of that stuff is being implemented with AspView trunk (versions 1.0.4.x) that works with Castle trunk.

If anyone wishes me to bubble it down to the 1.0.3.x branch (for Castle RC3), please leave your comments here. Unless I'll see that people actually want that I would probably not make the effort.

What Drives Me to Excel

on December 21st, 2007 at 7:39am 3 responses

Not MS-Excel.

 

As if it was not enough that wife has graduated her B.A. with honors, now she has just given a notice that she is about to gain honors on her M.A. studies, too.

And as if that's not enough, during the course of the studies, she has been employed at 80%-100%.

And now she starts looking at doing a Ph.D.

 

Now I feel the urge to complete my damn Bachelor's (and I'm around 84, so no honors for me), and learn so much, and code that much so I'd become a great good better-than-I-am-now developer, and just to try and keep up.

 

 

 

That's Wife holding a Cat:
Wife holding a Cat

 

Me, not holding by liqueur:
Not holding my liquer

Unit Testing 101 Article

on December 20th, 2007 at 9:33pm 0 responses

Usually I won't just link to another's post, but this one is a very good introductory level Unit Testing 101 Article, covering basics of the idea, and basic of nUnit and Rhino.Mocks.

 

A must read for Unit Testing newbies.

Over Engineering and Hammer Factories

on December 19th, 2007 at 9:28am 0 responses

I really do not know how I missed this thread.

So funny, so true.

http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12

If ever you need to convince someone to KISS, that's the source.

And if that's not enough, you have a shorter version at http://ayende.com/Blog/archive/2007/12/18/Choices.aspx

New stuff in AspView

on December 13th, 2007 at 2:36pm , , 2 responses

I'm pleased to announce that the first step of AspView refactoring is over. The pre-compilation process is now way more coherent and easy to follow and to test. Soon enough, as I'll complete adding a service locator to the mix, it would also be easily extensible.

 

What can you do now that you couldn't have done before? Use a custom base class for views.

For example: let's say that you have created a supercool helper. You'd probably name it SuperCoolHelper. Now you register that helper on the controller:

[Helper(typeof(SuperCoolHelper))]
public class MyController ...

 

You can, ofcourse declare it on every view:

<aspview:parameters>
<%
SuperCoolHelper SuperCoolHelper;
%>
</aspview:parameters>

<%=MyCoolHelper.CoolStuff() %>

You can also use the DictionaryAdapter and add the helper to the base view interface:

public interface IView
{
    SuperCoolHelper SuperCoolHelper { get; set; }
}

...

<% Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime<IView>" %>

...
<%=view.MyCoolHelper.CoolStuff() %>

But now you can create a base class for the view:

The base class:

public class MyView : AspViewBase
{
    SuperCoolHelper SuperCoolHelper { get { return (SuperCoolHelper)Properties["SuperCoolHelper"]; } }
}

A mocked class that inherit from Web.UI.Page to make intellisense play nicely:

public class MyViewAtDesignTime : ViewAtDesignTime
{
    SuperCoolHelper SuperCoolHelper { get { throw new NotImplementedException("useless"); } }
}

and in the view:

<% Page Language="C#" Inherits="MyViewAtDesignTime" %>
...
<%=MyCoolHelper.CoolStuff() %>

You can mix that with the DictionaryAdapter integration:

<% Page Language="C#" Inherits="MyViewAtDesignTime<IPostView>" %>
... <%=MyCoolHelper.CoolStuff(view.Post.Title) %>

As usual: http://www.aspview.com

A little markup&#43;css challenge

on December 7th, 2007 at 9:35am , , 1 responses

After reading the challenge on Dror's blog (Hebrew) I decided to post my answer here.

In short, for non hebrew readers, Dror is asking for a markup+css solution for the next layout:

 css layout

no javascript allowed for layout purposes.

 

Oh, and the center column can be long, so the left and right columns should stretch with it.

 

I have added another prequisite: the center content must come before the side contents (for accessibility).

 

That's my simplistic answer:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional-dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Dror Engel's blog rocks</title>
    <style type='text/css'>
    div, body {padding:0, margin:0}
    #right-column
    {
        background-color:#FFA
    }

    #left-column
    {
        float:left;
        width: 500px;
        background-color:#FAF
    }

    #center-column
    {
        float:right;
        width:400px;
        background-color:#AFF
    }
    div.break
    {
        clear:left;
    }

    </style>
    <script type='text/javascript'>
    function stretchCenter() {
        var center = document.getElementById('center-column');
        center.innerHTML += '<br /> Blah blah blah';
    }
    </script>
</head>
<body>
    <div id='right-column'>
        <div id='left-column'>
            <div id='center-column'>
            <button onclick='stretchCenter();'>Streach Center</button> <br />
            Center <br />
            Center <br />
            Center <br />
            </div>
            Left
        </div>
        right <br />
        <div class='break'></div>
    </div>
</body>
</html>

 

 

demo is here.

AspView refactoring status

on December 4th, 2007 at 10:13pm , , 0 responses

77 tests, all green.

That's all new tests from the last week.

I think it's almost stable enough for releasing it on aspview.com

I'll just put the old tests back in (with Ignore) as regression tests, until I'm comfortable enough to remove.

 

So - custom base classes for views are just around the corner.

Right after that - better extensibility (through custom Pre Compilation Steps provider and MarkupTransformation Provider)

 

you can of course watch the progress on svn (it's all on the trunk, so if you're using trunk for production, please restrain yourself a few more days ...)

 

stay tuned ...

Cool vs Uncool in programming languages

on December 4th, 2007 at 6:30am , 4 responses

Have just read Ayende's post about C#/Java vs Boo/Ruby.

Tried to comment, but then I decided it's worth a post.

I'd say that the difference is MAF - Management Acceptance Factor

  • Java and C# has the Big Names behind them, so managers are comfortable. Ruby and Boo does not, hence ...
  • Java is v6, c# is v3, while Ruby and Boo are v0.x - another Management Scary.

Boo is also a way too cool/strange/creepy name for a distinguished suit to grasp.

It's like when you're a collage girl, and you want to introduce your new boyfriend to your mama. It doesn't matter that he has a BSc and MBA plus 3 castles in the Swiss alps. If he'd first show up to the family on his way-too-cool motorcycle, then you're going to be grounded.

 

When I approached my last manager about MonoRail, and told him that the views will be written in 'Boo', he got all scared. Then I wrote AspView, views to be written in c#, and he gave consent to go MonoRail.
Even though, at least at that time, Brail was way more mature than AspView.
The 'cooler' languages needs to be marketed to management.

Ruby works in Eclipse. I wonder who is going to start an OSS effort to create a decent Boo plugin for VS2008 (based on the VS2008 shell).

Make it demoable, make it look 'official', and MAF would go way higher.


Follow

Statistics

Posts count:
447
Comments:
950