Page 1 of 1 in the ASPNETMVC category
# Friday, August 06, 2010
Close up blog entry

The ClientBuildManager is a .NET BCL class that facilitates compiling ASP.NET markup files outside of IIS. I did run into an issue using this class which others may hit as well.

I compiled some ASP.NET MVC .aspx views and tried to get the type using ClientBuildManager.GetCompiledType, but the GetCompiledType function returned null. Hmm…I could see the compilation was working because the assemblies were seemingly generated correctly.

It ends up that the type would not load because the calling project did not reference all the assemblies needed to load the type. The ClientBuildManager compiles the web components in a separate application domain. When trying to retrieve the type, the assembly is loaded into the calling application domain, and then the type retrieval is attempted. If the type can not load no error is thrown, instead you get a null return value.

So make sure the application using ClientBuildManager references all assemblies referenced by the web application you are compiling.

I hope this saves someone some time. It took a bit of head banging to figure this one out. I had to debug down into System.Web to figure out what was going on :-(

Share/Bookmark
Friday, August 06, 2010 10:53:45 PM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, July 21, 2010
Close up blog entry

There is no clear cut mechanism provided by the ASP.NET MVC framework to pass data from a view to it’s master page. I’ve been using a technique that I’m reasonably happy with, which I’ll describe in this blog post.

For starters, my example will be using the ITypeInstanceDictionary provided in the TTC Tools. Please read my blog post pass data from an ASP.NET MVC controller to view to learn more. The code shown in this blog post is included in a demo web application on the TTC Tools GitHub page.

There are many scenarios in which you want to drive master page values from the view. For example: some CSS styling that exists in the master page will be dependent on the view. Personally I feel this should not be driven by the controller, as there are many situations in which CSS styles are purely display driven.

I’ll summarize the basic concepts for passing data from the view to it’s master page.

  • Create an interface that is used by the master page for use in the master page markup code, and allow the view to override these values.
  • Setup the master page view data at the top of the master page
  • Follow up the master page code with a content place holder.
  • This content place holder will be used by the view to override any master page data values.

My example code will show how to override the pages body element id in the master page from a view.

The following code snippet shows an example master page implementation:

Setup ASP.NET MVC Master Page To Allow View To Override Data

The view can override master page view data by creating a content control for the master page’s content place holder which follows the setup of the master page’s view data.

ASP.NET MVC View Pass Data To Master Page

The ASP.NET MVC view engine rendering execution flow will start at the top of the master page and then flow into the content place holders. This allows the view to override the master page view data before it is used later in the master page markup code.

I created a screen cast which might help explain this technique in a bit more detail.

If you need any further explanation or have any questions please let me know. I hope someone finds this useful :-)

Share/Bookmark
Wednesday, July 21, 2010 11:05:35 PM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 
Close up blog entry

The default mechanism for passing data from an ASP.NET MVC controller to the view is to use the ViewData property of the controller and view which is of type ViewDataDictionary. The ViewDataDictionary is a string indexed collection of type object. My main issue with this mechanism is two fold. I’m not a big fan of string indexed collections and I don’t want to have to cast to get at the type of the class instance in the collection.

The next option is to use the Model property of the ViewDataDictionary. The Model property of ViewData allows a strongly typed way to pass data from the controller to the view. The question becomes what type should be used? One choice is to use a specific type for each controller action and view, but this gets a bit cumbersome. Instead I propose using a collection indexed by type which is assigned to the Model property of ViewData.

I created a project called TTC Tools which houses the ITypeInstanceDictionary, which provides a generic mechanism to pass various types from controller to view in a more strongly typed way than the ViewDataDictionary.

I documented some basic usage scenarios for the type instance dictionary on my wiki. I also created a screen cast to document basic usage in an ASP.NET MVC application.

The basic idea is the dictionary provides the template functions Add<T>, Get<T>, and Contains<T>. The type T is used as the indexer of the dictionary, so instances of various types can be added and retrieved from the dictionary.

A very basic usage scenario from a unit test is illustrated as follows:

ITypeInstanceDictionary Basic Usage Example

The type does not have to be specified for the Add call, as the declared type of the parameter will be used. The Get call must declare the type, as the type T is used for the dictionary index.

The type instance dictionary does allow multiple instances of the same type to be added, but only if some other type of instance identifier is supplied. For example an enumeration can be used to differentiate the types. An example of adding and retrieving multiple instances of the same type using an enumerated type for the instance id follows:

ITypeInstanceDictionary Multiple Of Same Instance Example

Basic use in an ASP.NET MVC application

For convenience, derive all your controllers from a base controller that provides a  property of type ITypeInstanceDictionary. My example uses a property named TypeViewData.  The code for the base controller follows:

   public class BaseController : Controller
   {
      ITypeInstanceDictionary _typeViewData = new TypeInstanceDictionary();

      public ITypeInstanceDictionary TypeViewData
      {
         get
         {
            return _typeViewData;
         }
         set
         {
            _typeViewData = value;
         }
      }
   }

Controller actions that return a ViewResult should use the controller View function overload which accepts the model argument. The TypeViewData property should be passed into the view function as follows:

Return ITypeInstanceDictionary From ASP.NET MVC Controller Action

The view should then use the template version of the ViewPage class, with the type set to TTC.Tools.ITypeInstanceDictionary. The template version of the ViewPage class strongly types the Model property of the View.  The Model property can then use the Get<T> function to retrieve the data sent from the controller. An example of the view code follows:

ITypeInstanceDictionary ASP.NET MVC View Example

You can find the code, which includes a sample web site using the type instance dictionary, at the TTC Tools GitHub page. I’ve also created some basic documentation on my wiki.

If you have any questions please let me know!  I’m not sure if others will find this useful, but you never know :-)

Share/Bookmark
Wednesday, July 21, 2010 10:40:22 PM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, March 15, 2010
Close up blog entry

I needed some code to determine if an ASP.NET MVC view exists. For a particular controller I’m dynamically determining the view to return by name. I looked at the source code for ASP.NET MVC and figured out how views are found and came up with the following code:

public ActionResult Page(string viewName)
{
   ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, viewName, null);

   if (viewResult.View == null)
   {
      throw new HttpException(404, "404 - View Not Found");
   }

   return View(viewName);
}

This function is a member of a controller class. I wanted to check if the view exists and return a HTTP 404 result if the view is not found. There is likely a better way to wrap up the call in a helper function, but this illustrates the principle.

There may be another or better way to do this, but this works for now and hopefully might help someone else as well :-)

Share/Bookmark
Monday, March 15, 2010 9:25:18 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |