Tag Archives: ASP.NET

Adding Styles to Built in Editor Templates in Razor

I thought I’d blog about this thing I keep forgetting the syntax for and I’m sick of Googling for it. It’s a bit of a niche thing in Razor. First, some background.

Previous to MVC 5, you could not add any styling to any of the built-in EditorTemplates. So, if you wanted to add a Bootstrap style to an input, you had to fall back on the simple Editor extension method:


@Html.EditorFor(m => m.Name, new { @class = "input-lg"}) // won't work
@Html.Editor ("Name", new { @class = "input-lg"}) // used to be OK - before MVC 5

The EditorTemplate would simply ignore the style. And if it happened to be the first time you bumped up against that foible, you probably blew half a day figuring out that it was not supported.

Someone whispered in Microsoft’s ear, because they changed this in MVC 5 (possibly the 5.1 release). The following syntax enables you to have your cake and eat it:


@Html.EditorFor(m => m.Name, new { HtmlAttributes = new { @class = "input-lg" }})

Note, you now have to use that new syntax with the simple Editor extension method as well.

HtmlHelper for Javascript Script Elements (Tags)

I wrote an HtmlHelper for Javascript elements which, I believe, makes for a more maintainable codebase for adding script elements to a view:

        public enum JavascriptPathType
        {
            Relative = 0,
            FullWebPath = 1
        };

        public static MvcHtmlString Script(this HtmlHelper helper, string jsFileName, JavascriptPathType pathType)
        {
            // Instantiate a UrlHelper
            var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);

            // Create tag builder
            var builder = new TagBuilder("script");

            switch (pathType)
            {
                case JavascriptPathType.Relative: builder.MergeAttribute("src", urlHelper.Content("~/Scripts/" + jsFileName));
                    break;
                case JavascriptPathType.FullWebPath: builder.MergeAttribute("src", urlHelper.Content(jsFileName));
                    break;
            }

            // Add attributes
            builder.MergeAttribute("type", "text/javascript");

            // Render tag. Note: script tags have to have an End tag and cannot be self-closing.
            return new MvcHtmlString(builder.ToString(TagRenderMode.Normal));
        }

The most common scenario is where your javscript file is located in the Scripts directory of your project, in which case, all you need to do is pass in the name of the javascript file:

@Html.Script("jquery-1.8.2.min.js", JavascriptPathType.Relative);

This saves you from typing the script tags and the text type=”text/javascript” everytime.
I also added the custom enum JavascriptPathType to account for scenarios where the src of the script tag is pointing to someplace other than within your own project. For example, if you were using the Google maps API, the usage would be:

@Html.Script("http://maps.google.com/maps/api/js?sensor=false", JavascriptPathType.FullWebPath);

I’m thinking next will be the same kind of helper for Css files.

Working on a Page With a Query String Parameter

Quite often in web development, we use query strings to pass values to a page. It is a convenient way to pass non-sensitive data to a page, and also makes the URL hackable (allowing users to plug in their own values in the URL and reloading the page for the information relevant to those values).

When developing these pages in ASP.NET webforms, there is a neat little trick that can be employed to save you stacks of time. You can configure   Visual Studio to load a particular URL, with a particular value locked and loaded in the Query String. This saves you having to load the page from which the user must navigate, select/enter values and click a submit button to kick off the navigation to the page which you are working on.

Here’s how:

  1. Click on the Web Project in Solution Explorer and holding down the ALT key, depress the Enter key (or just right-click and click Properties).
  2. Click on the Web tab.
  3. Then, select the Start URL radio button and enter in your URL plus query string as depicted below:

VisualStudioWebProperties

Once you have it all working nicely, you can go back and test the whole thing from the navigation of the previous page to this one.

If you are working on such a page for many hours (even days), this tip will save you heaps of time, and the tediousness of repeatedly clicking through to your destination page.

Items Collection

The Items collection, which is a property of the Page class, has one particular quality that distinguishes it from the Session object. It only exists for the lifetime of a single request. That being the case, I’m not really sure what value it adds. If I needed an object in memory over the course of a Page’s life, I would just create a page variable, rather than add a value to the Items collection.

However, the Items collection which is a property of the Page object is different to the Items collection on the HttpContext.Current object. There is definitely a use case for this particular collection, which fills a particular niche.

If you are building one or more HttpModules and you would like to:

  1. store something in memory, but only for the duration of a single request;
  2. be able to retrieve that item in another HttpModule, or in the HttpHandler targeted by the request,

then the HttpContext.Current.Items collection is the way to go.

I’ve prepared a very simple example for download. In that example, there is a simple HttpModule which I have created called NameUserModule. I set a variable called NameOfMe in the HttpApp_BeginRequest event handler and I retrieve it in the Page_Load handler of the Default.aspx page (the targeted HttpHandler for the request).

ASP.NET Web Forms MVP

I like coding to patterns. And one pattern I really like is the Model View Presenter (MVP) pattern. Whilst the Patterns and Practices group’s implementation of this pattern (Web Client Software Factory) is good for big applications with a multitude of business modules, it is too heavy for smaller applications. This is where the ASP.NET Web Forms MVP project fills a niche nicely.

Put together by an Australian duo (Tatham Oddie and Damian Edwards), ASP.NET Web Forms MVP is a very nice implementation of the MVP pattern using the WebForms flavour of ASP.NET. With ASP.NET MVC all the rage these days, I like the fact that these guys went off and did their own thing, injecting new life into the WebForms universe. And they have incorporated messaging! Now that is really handy and feels like possible lessons learnt from some of the XAML technologies.

I have put together a really simple example to give you a taste. The charter I set for this example was to showcase the typical lifecycle of a request, starting at the View, going via the Presenter and hitting a data layer to retrieve some data from an XML file and display it in a grid (back on the View). There’s no paging or sorting on the Grid – unnecessary complexity for this style of example.

In the download code, you will find a solution with the following structure:

I have deliberately used the same prefix for the Logic and DataAccess projects (i.e. the name of the web project) as I have relied on convention for Presenter discovery.

Firstly, I need to create a model for my page:

public class DisplayAlbumsModel
{
	public List<Album> Albums { get; set; }
	public class Album
	{
		public string Id { get; set; }
		public string Artist { get; set; }
		public string Title { get; set; }
	}
}

This will provide the data context which I can hydrate in my Presenter and make available to my View.

Speaking of Views, I need an interface for the View:

public interface IDisplayAlbumsView : IView<DisplayAlbumsModel>
{
	event EventHandler RetrieveAlbums;
}

One event will do. This will be raised by the View to the Presenter, which will subscribe to it in its Load method. With composing components as the desired approach, we will now implement that View as a user control, over in the Webapp project. We will then chuck that user control on a very basic, bare-bones web page. The user control inherits from MvpUserControl<DisplayAlbumsModel>, strongly typed to my Model. It also implements IDisplayAlbumsView, raising the member event RetrieveAlbums in the Page_Load event handler:

public partial class DisplayAlbumsControl : MvpUserControl<DisplayAlbumsModel>, IDisplayAlbumsView
{
	protected void Page_Load(object sender, EventArgs e)
	{
		if (!IsPostBack)
		{
			RetrieveAlbums(this, EventArgs.Empty);
			this.AlbumsGridView.DataSource = Model.Albums;
			this.AlbumsGridView.DataBind();
		}
	}

	public event EventHandler RetrieveAlbums;

	protected void AlbumsGridViewRowcommand(object sender, GridViewCommandEventArgs e)
	{
		// do stuff here. E.g. redirect to a page with details about the selected album.
	}
}

Finally, over to the Presenter back in the Logic project, which inherits from the WebFormsMvp.Presenter class, strongly typed to our View:

public class DisplayAlbumsPresenter : Presenter<IDisplayAlbumsView>
{
	private readonly ChinookDbHelper dataAccessHelper;

	public DisplayAlbumsPresenter(IDisplayAlbumsView view) : base(view)
	{
		dataAccessHelper = new ChinookDbHelper();
		View.RetrieveAlbums += View_RetrieveAlbums;
	}

	void View_RetrieveAlbums(object sender, EventArgs e)
	{
		List<DisplayAlbumsModel.Album> albums = new List<DisplayAlbumsModel.Album>(); // a collection of Domain objects.
		var albumsData = dataAccessHelper.GetAlbums(); // get the tuples from the Data Layer

		//  Transform the raw data to a collection of Domain objects.
		foreach (var album in albumsData)
		{
			albums.Add(new DisplayAlbumsModel.Album {Artist = album.Item3, Id = album.Item1, Title = album.Item2});
		}

		View.Model.Albums = albums;
	}
}

The presenter discovery is done by convention. To demonstrate what the framework looks for, all I have to do is add a Typo to the Presenter’s namespace. The stack trace tells the whole story. First it looks for the PresenterBinding attribute (more on that later). After that, it searches for it in certain namespaces:

AttributeBasedPresenterDiscoveryStrategy:
– could not find a [PresenterBinding] attribute on view instance ASP.controls_displayalbumscontrol_ascx

ConventionBasedPresenterDiscoveryStrategy:
– could not find a presenter with type name WebFormsMvpSimplePage.DisplayAlbumsPresenter
– could not find a presenter with type name WebFormsMvpSimplePage.Logic.Presenters.DisplayAlbumsPresenter
– could not find a presenter with type name WebFormsMvpSimplePage.Presenters.DisplayAlbumsPresenter
– could not find a presenter with type name WebFormsMvpSimplePage.Logic.DisplayAlbumsPresenter
– could not find a presenter with type name WebFormsMvpSimplePage.DisplayAlbums
– could not find a presenter with type name WebFormsMvpSimplePage.Logic.Presenters.DisplayAlbums
– could not find a presenter with type name WebFormsMvpSimplePage.Presenters.DisplayAlbums
– could not find a presenter with type name WebFormsMvpSimplePage.Logic.DisplayAlbums

So we can see how managing naming convention can be used to wire up the components of the MVP pattern.

If you want to use the PresenterBinding attribute for Presenter discovery, that is easily implemented by decorating the usercontrol class as follows:

[PresenterBinding(typeof(DisplayAlbumsPresenter), 
ViewType = typeof(IView<DisplayAlbumsModel>), 
BindingMode = BindingMode.Default)]

The attribute is the WebFormsMvp.PresenterBindingAttribute which has 3 properties: BindingMode, PresenterType and ViewType. Further examination of that attribute is beyond the scope of this post.

I’d like to thank Oddie and Edwards for this cool and light framework. Perfect for the scenario where you don’t want the overhead of the Web Client Software Factory, but you want the trimmings, familiarity and RAD aspects of Web Forms, plus the testability that the MVP pattern provides.

Download Code