Brendan Enrick's Blog

Daily Software Development.


Types of ASP.NET MVC 3 Action Results

by Brendan Enrick Thursday, August 11 2011 10:00

This will surprise some of you that know me or the company I work for, but not all of our staff are experts with ASP.NET MVC. In fact, I am hoping that the couple who aren’t will read this post and learn a little bit more about the topic.

Since the actions of controllers in MVC are dealt with constantly, I think it is a good place to start. This post is going to briefly describe the different types of results that are available to you in ASP.NET MVC 3. I will show some of the code that makes them work, which should make all of this seem a lot less complicated.

When creating new controllers in ASP.NET MVC 3, they will come with one or more actions by default. This depends on whether you selected a template which includes extras for you. The Empty controller template comes with an Index action with a return value of type ActionResult.

ActionResult

The action result is a very generic return value for an action. This is because it is the abstract base class for other types of actions. It is actually a very simple class having only one method that needs implementing.

public abstract class ActionResult
{
public abstract void
ExecuteResult(ControllerContext context);
}

Inheriting from the ActionResult are the following classes:

  • ContentResult
  • EmptyResult
  • FileResult
  • HttpStatusCodeResult
  • JavaScriptResult
  • RedirectResult
  • RedirectToRouteResult
  • ViewResultBase

These are the classes that inherit from ActionResult indirectly:

  • FileContentResult
  • FilePathResult
  • FileStreamResult
  • HttpNotFoundResult
  • HttpUnauthorizedResult
  • PartialViewResult
  • ViewResult

ViewResultBase, ViewResult, and PartialViewResult

The ViewResult is the most common concrete type you will be returning as a controller action. It has an abstract base class called ViewResultBase, which it shares with PartialViewResult.

It is in the ViewResultBase abstract base class that we get access to all of our familiar data objects like: TempData, ViewData, and ViewBag.

PartialViews are not common as action results. PartialViews are not the primary thing being displayed to the user, that is the View. The partial view is usually a widget or something else on the page. It’s usually not the primary content the user sees.

This is the common return syntax, and it means that you’re returning a ViewResult.

return View();

That is actually a call to the base Controller.View method, which is just going to call through with some defaults.

protected internal ViewResult View()
{
return View(null, null, null);
}

 

The beauty of ASP.NET MVC is actually in its simplicity though, because all that really did was create our ViewResult for us. If we take a look at the method that is being called you can see that we’re just taking a little shortcut and keeping our action clean of this code we would otherwise repeat every time we wanted a ViewResult.

protected internal virtual ViewResult View(
string viewName, string masterName, object model)
{
if (model != null)
{
ViewData.Model = model;
}

return new ViewResult
{
ViewName = viewName,
MasterName = masterName,
ViewData = ViewData,
TempData = TempData
};
}

Notice how simple that really is. All it did was put the model data in if we specified it, give the ViewResult the Controller properties that we set already, and assign the viewName and masterName.

Keep in mind, that we already saw that the abstract method in the ActionResult was the ExecuteResult method. The last two things to look at with the ViewResultBase are the ExecuteResult method and its abstract method FindView, which is being implemented by ViewResult and PartialViewResult.

public override void ExecuteResult(
ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (String.IsNullOrEmpty(ViewName))
{
ViewName = context.RouteData
.GetRequiredString("action");
}

ViewEngineResult result = null;

if (View == null)
{
result = FindView(context);
View = result.View;
}

TextWriter writer = context.HttpContext.Response.Output;
ViewContext viewContext = new ViewContext(
context, View, ViewData, TempData, writer);
View.Render(viewContext, writer);

if (result != null)
{
result.ViewEngine.ReleaseView(context, View);
}
}

This method is also not very complicated. It checks to make sure we have context, and then if we don’t have the ViewName then we get that information from the RouteData. Remember in MVC that the name of action is included in the RouteData, so we can use that as the default view name. This means that in the Index action, if we just call View(), it will give us a ViewName of “Index”.

We then get the view we’re looking for by calling the FindView abstract method, which means we’re calling through to either ViewResult and PartialViewResult. Those I am not going to get into the guts of, but each one is going to try to find the correct view based on the name using its collection of ViewEngines.

Once we have the view, we are able to tell it to render itself using the context and the TextWriter we give to it.

That’s all there is to a ViewResult.

ContentResult

The content result lets you define whatever content you wish to return. You can specify the content type, the encoding, and the content. This gives you control to have the system give whatever response you want. This is a good result to use when you need a lot of control over what you’re returning and it’s not one of the standards.

Its ExecuteResult override is extremely simple.

public override void ExecuteResult(ControllerContext context) 
{
if (context == null)
{
throw new ArgumentNullException("context");
}

HttpResponseBase response = context.HttpContext.Response;

if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Content != null)
{
response.Write(Content);
}
}

It just puts what you specified directly into the response.

EmptyResult

There is no simpler result than the EmptyResult. All it does is override the ExecuteResult method and since that method is void, the method is empty.

I really don’t think I need that code snippet for this one.

FileResult, FileStreamResult, FilePathResult, and FileContentResult

If you want specific actions to send files as the response, then the FileResult is for you. Sadly, the FileResult is abstract, so you’ll need to use one of the inheriting classes instead. Each of these actually just overrides the WriteFile method for the abstract FileResult class.

If you want to just send the contents of the file back with the array of bytes for the file, then you want the FileContentResult. It uses the response’s OutputStream and writes those bytes directly into the stream sending it down to the user.

If you want to transmit the file using its name, you can use FilePathResult, which will call through a whole bunch of layers finally down to the HttpResponse. Once there it is going to create a new FileStream for your file and write the stream to the response allowing the file to be accessed from your action.

If you’ve already got a stream you can use the FileStreamResult, which will read all of the data from your stream and then write it into the OutputStream to be send back in the response.

These really aren’t all that complicated, but if you want to have control over the file downloads in your application, this is a great way to do it. These give you the power to put any code you want in your action before you give back the FileResult.

HttpStatusCodeResult

The HttpStatusCodeResult is as simple as the ContentResult. In fact, the two are quite similar since they both just directly modify the response object.

This one lets you return any StatusCode you want and you can include a StatusDescription for specifics.

public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}

context.HttpContext.Response.StatusCode = StatusCode;
if (StatusDescription != null)
{
context.HttpContext.Response
.StatusDescription = StatusDescription;
}
}

See how simple that is? It’s basically just two lines of code with some null checking included.

HttpNotFoundResult and HttpUnauthorizedResult

These two results are actually just implementing the HttpStatusCodeResult, which means that they are very simple and just set the StatusCode to 404 for the HttpNotFoundResult and 401 for the HttpUnauthorizedResult.

JavaScriptResult

About as simple as plenty of the others, this is just a quick way of getting JavaScript returned from a action. It’s similar to the ContentResult, but it has the ContentType hardcoded to “application/x-javascript” and just writes out the Script property.

public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}

HttpResponseBase response = context.HttpContext.Response;
response.ContentType = "application/x-javascript";

if (Script != null)
{
response.Write(Script);
}
}

JsonResult

This one is a bit more complex, but still not very. It also has hardcoded its ContentType, but what makes it a bit more complex is that it uses a hardcoded JavaScriptSerializer to serialize the JSON data before writing it directly to the response.

public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
String.Equals(context.HttpContext.Request.HttpMethod,
"GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(
MvcResources.JsonRequest_GetNotAllowed);
}

HttpResponseBase response = context.HttpContext.Response;

if (!String.IsNullOrEmpty(ContentType)) {
response.ContentType = ContentType;
}
else {
response.ContentType = "application/json";
}
if (ContentEncoding != null) {
response.ContentEncoding = ContentEncoding;
}
if (Data != null) {
JavaScriptSerializer serializer =
new JavaScriptSerializer();
response.Write(serializer.Serialize(Data));
}
}

RedirectResult and RedirectToRouteResult

These to are a little bit more complex, but both are ways of redirecting. Each one can either be a permanent or temporary redirect and they both just use the Redirect methods on the Response object.

For redirecting to a route, it is going to generate a URL to the route using the UrlHelper’s GenerateUrl method. For the RedirectResult it is instead going to use the UrlHelpers GenerateContentUrl method.

Either of these two are useful, and both will maintain your TempData if you need to pass something along with the redirect, all you have to do is put it in TempData.

Conclusion

I hope you’ve learned that the results of actions in MVC are not actually very complicated, but there is a lot you can do with them. You’re not being forced into just displaying views. You have a lot more control than that. None of them were that complicated were they? The code under the hood is not always complicated, so it’s worth taking a look from time to time. If you examine how something is working, it’s often far easier to use it.

Difference Between ViewBag and ViewData in MVC 3

by Brendan Enrick Wednesday, August 10 2011 10:00

If you’re new to ASP.NET MVC, you might be wondering what these two things are and when to use each one. If you’ve been using MVC and are just new to version 3 of MVC, you are probably wondering what this new ViewBag is for and if it’s different from the ViewData you’ve been using. In the beginning of the Summer, I had the opportunity to explain this difference to the two NimblePros interns when they started working on ASP.NET MVC 3 for the first time. This post should serve as a reference for them, me, and anyone else who is interested in knowing more about these two objects.

ViewBag and ViewData serve the same purpose in allowing developers to pass data from controllers to views. When you put objects in either one, those objects become accessible in the view. This is one way we interact between the view and the controller in ASP.NET MVC. We pass data from the view to the controller by placing it in these objects.

How ViewData Works

ViewData is a dictionary of objects that are accessible using strings as keys. This means that we will write code like this:

In the Controller

public ActionResult Index()
{
var softwareDevelopers = new List<string>
{
"Brendan Enrick",
"Kevin Kuebler",
"Todd Ropog"
};

ViewData["softwareDevelopers"] = softwareDevelopers;

return View();
}

In the View

<ul>
@foreach (var developer in (List<string>)ViewData["softwareDevelopers"])
{
<li>
@developer
</li>
}
</ul>

Notice that when we go to use out object on the view that we have to cast it since the ViewData is storing everything as object. Also, we need to be careful since we’re using magic strings to access these values.

How ViewBag Works

ViewBag uses the dynamic feature that was added in to C# 4. It allows an object to dynamically have properties added to it. The code we write using ViewBag will look like this:

In the Controller

public ActionResult Index()
{
var softwareDevelopers = new List<string>
{
"Brendan Enrick",
"Kevin Kuebler",
"Todd Ropog"
};

ViewBag.softwareDevelopers = softwareDevelopers;

return View();
}

In the View

<ul>
@foreach (var developer in ViewBag.softwareDevelopers)
{
<li>
@developer
</li>
}
</ul>

Notice here that we did not have to cast our object when using the ViewBag. This is because the dynamic we used lets us know the type. Keep in mind that these dynamics are as the name suggest, dynamic, which means that you need to be careful as these are basically magic properties instead of magic strings.

ViewBag and ViewData Under the Hood

So these two things seem to work almost exactly the same. What’s the difference? The difference is only in how you access the data. ViewBag is actually just a wrapper around the ViewData object, and its whole purpose is to let you use dynamics to access the data instead of using magic strings. Some people prefer one style over the other. You can pick whichever you like. In fact, because they’re the same data just with two different ways of accessing it, you can use them interchangeably. (I don’t recommend this, but you can do it.) If you want you are able to put data into the ViewBag and access it from the ViewData or put stuff in the ViewData and access it in the ViewBag.

This is all that the ViewBag property is. It’s just a DynamicViewDataDictionary with the ViewData as its data.

public dynamic ViewBag 
{
get
{
if (_dynamicViewData == null)
{
_dynamicViewData =
new DynamicViewDataDictionary(() => ViewData);
}
return _dynamicViewData;
}
}

Then when we access the dynamic members of the DynamicViewDataDictionary, we are actually just getting this override of the DynamicObject’s TryGetMember. In this method, it’s just using the name of the member we tried to access as the string key for the ViewData dictionary.
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
result = ViewData[binder.Name];
return true;
}

So for a short answer:

These two objects are two different ways of accessing the exact same data. The ViewBag is just a dynamic wrapper around the ViewData dictionary.

Custom Model Binders in ASP.NET MVC

by Brendan Enrick Friday, July 15 2011 10:00

In ASP.NET MVC, our system is built such that the interactions with the user are handled through Actions on our Controllers. We select our actions based on the route the user is using, which is a fancy way of saying that we base it on a pattern found in the URL they’re using. If we were on a page editing an object and we clicked the save button we would be sending the data to a URL somewhat like this one.

 

Notice that in our route that we have specified the name of the object that we’re trying to save. There is a default Model Binder for this in MVC that will take the form data that we’re sending and bind it to a CLR objects for us to use in our action. The standard Edit action on a controller looks like this.

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here

return RedirectToAction("Index");
}
catch
{
return View();
}
}

If we were to flesh some of this out the way it’s set up here, we would have code that looked a bit like this.

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
Profile profile = _profileRepository.GetProfileById(id);

profile.FavoriteColor = collection["favorite_color"];
profile.FavoriteBoardGame = collection["FavoriteBoardGame"];

_profileRepository.Add(profile);

return RedirectToAction("Index");
}
catch
{
return View();
}
}


What is bad about this is that we are accessing the FormCollection object which is messy and brittle. Once we start testing this code it means that we are going to be repeating code similar to this elsewhere. In our tests we will need to create objects using these magic strings. What this means is that we are now making our code brittle. If we change the string that is required for this we will have to go through our code correcting them. We will also have to find them in our tests or our tests will fail. This is bad. What we should do instead is have these only appear on one place, our model binder. Then all the code we test is using CLR objects that get compile-time checking. To create our Custom Model Binder this is all we need to do is write some code like this.
public class ProfileModelBinder : IModelBinder
{
ProfileRepository _profileRepository = new ProfileRepository();

public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
int id = (int)controllerContext.RouteData.Values["Id"];
Profile profile = _profileRepository.GetProfileById(id);

profile.FavoriteColor = bindingContext
.ValueProvider
.GetValue("favorite_color")
.ToString();


profile.FavoriteBoardGame = bindingContext
.ValueProvider
.GetValue("FavoriteBoardGame")
.ToString();

return profile;
}
}

 

Notice that we are using the form collection here, but it is limited to this one location. When we test we will just have to pass in the Profile object to our action, which means that we don’t have to worry about these magic strings as much, and we’re also not getting into the situation where our code becomes so brittle that our tests inhibit change. The last thing we need to do is tell MVC that when it is supposed to create a Profile object that it is supposed to use this model binder. To do this, we just need to Add our binder to the collection of binders in the Application_Start method of our GLobal.ascx.cs file. It’s done like this. We say that this binder is for objects of type Profile and give it a binder to use.

ModelBinders.Binders.Add(typeof (Profile), new ProfileModelBinder());

Now we have a model binder that should let us keep the messy code out of our controllers. Now our controller action looks like this.

[HttpPost]
public ActionResult Edit(Profile profile)
{
try
{
_profileRepository.Add(profile);

return RedirectToAction("Index");
}
catch
{
return View();
}
}

That looks a lot cleaner to me, and if there were other things I needed to do during that action, I could do them without all of the ugly binding logic.

ASP.NET Dynamic Data, MVC, and AJAX

by Brendan Enrick Thursday, October 1 2009 14:15

I’ve been having an interesting conversation with Peter Blum about the different directions in which ASP.NET is currently developing. He has some very interesting points that he is making about this topic. So he asked me if I use dynamic data, which is of course how all of this conversation started. I informed him that most of my exposure to ASP.NET Dynamic Data has just been playing around with it. I really haven’t done any applications using it. (I of course don’t consider little test applications and demos to be real applications.)

I also admitted that I’ve been heavily involved with MVC since the early beta versions of it. I didn’t mention at the time that I also started using AJAX very early on as well. I did a lot with “Atlas” as it was called at the time. His responding comment was quite interesting.

the Insiders are so heavily into MVC that we don’t have enough people who push Microsoft to improve the webforms technology

I really think that he makes a great point here since MVC got here we really don’t hear too many of the prominent voices talking about improvements that can be made to ASP.NET Web Forms. Yes, I know there are those who do not like MVC. I read some of their blogs. Some of their reasons are well thought out and very relevant. What I am seeing less often is people commenting on the things that can make web forms better.

Something I’ve said many times since MVC came around is that it is great for certain circumstances. If you’re in one of them, use MVC. If your task requires Web Forms, then use them. Heck, if you need classic ASP, go for it. Using the right tool for the job is extremely important. Just because you’ve mastered the hammer and the screwdriver doesn’t mean you should use them to dig a hole.

A trend that Peter also noted in our conversation is that Dynamic Data came around and there was a little bit of hype for it, but the hype largely died out. MVC, however, has had continual hype, growth, and attention since its mention. AJAX also had a large amount of support and a great following from MVPs, insiders, and influential people.

The thing with Dynamic Data though is that in concept it is a very cool idea and has the potential to be great. It, like all technology, needs to have feedback from the community. It is up to the developers to push Microsoft into developing the technology in the correct direction. I think this is one of the reasons that Peter has been working so hard on Dynamic Data.

With the early beta versions of ASP.NET MVC some of the “testability” was really not there. People trying to use it had to use workarounds to get things to work. For example controllers used to call a method to show the view. They didn’t return ActionResults as they do now. The problem is that it was hard to see what was called so you couldn’t really test it. So I created “fake” controllers to do my testing since the controllers were inadequate at the time. Developers using and giving feedback about what needed to change is what made that project a success.

Not sure if we can revitalize the interest in Dynamic Data and get the ball rolling in the right direction for it, but I can say that I’ve heard very little about it lately. So how about it? Willing to try out Dynamic Data and see how it can be made better?

Peter made DES Dynamic Data, which is supposed to enhance a lot of the aspects of ASP.NET Dynamic Data perhaps I’ll try it out and see if it makes Dynamic Data spectacular.

Building an MVC Gaming Statistics Site &ndash; Setting Up the Project

by Brendan Enrick Saturday, September 26 2009 17:36

Now that ASP.NET MVC has been around for a while there have been plenty of articles written about how leverage the technology to create powerful, lightweight web applications which are highly customizable and testable. I’ve discussed the advantages of using ASP.NET Forms and ASP.NET MVC plenty of times in the past, but just so no one thinks I am a forms hater I will say that I still create forms applications. Both MVC and Forms can coexist and they both have their advantages.

I will say that there is of course a learning curve for MVC. You don’t instantly know it just because you’ve used web forms. So yes, it will be like learning any new technology. However, I am writing this so that a transition can be easier. Rather than doing some demo application that doesn’t take into consideration real-life situations and circumstances I’ll be posting about an application I’ve been working on.

Background Information and Reason for Creating the Site

I am a member of the Boardgamers Of Greater Akron (BOGA), which if you hadn’t guessed from the name is a group of people who gather together the second Friday of every month to play board games. As games are completed the stats from the games are recorded onto sheets of paper and these stats will later be entered into a database.

Initially the founder of the group had been entering these game logs into the system using a local web forms application using the standard data entry controls. The entire site took about half an hour to an hour to create, so as you can guess it was kind of clunky and hard to use. From the data, I was able to write a bunch of SQL queries that were then used to calculate the stats from these games.

Creating the Solution, MVC Project, and Web Tests Project

I like to start by creating a solution first. I don’t want Visual Studio to create the solution for me because it will do a lot of stuff for me. I want to have control of the structure of my application, so I am going to create that first. This will let me organize my software project. To create a solution just create a new project of type Blank Solution. You can find that in the Other Project Types –> Visual Studio Solutions category.

01-NewSolution 

I named the solution based on the domain of the application. This is important to do since I don’t plan on referencing the domain in any of the projects in this solution. Since names get long and difficult to work with sometimes I am going to stick with shorter ones. I’ll alter their default namespaces so it is a little bit easier to deal with.

Before we can write any code we have to have a project in which to write this code, so how about if we create a new MVC project. I’ll name it based on the domain of our application, so I’ll go with Web. Since the

 02-NewMVCProject

Since we created this as an MVC site we will be prompted with the option to create a test project. Your Test Framework options will be populated with the test frameworks that you have installed that Visual Studio knows about. In this case I am just going to go with the Visual Studio Unit Test Framework since it defaulted to that. The differences between this and NUnit are negligible anyway.

 03-CreateWebTestProject

After you wait for Visual Studio to create the projects for you the following will appear in the Solution Explorer. The first step is deleting the AuthoringTests.txt file. Not sure why that needed to be included every single time a project is created. Maybe there is some way to turn it off just so I don’t have to delete it. Well it doesn’t matter anyway.

04-SlnExpl-DeleteAuthoringTests

I might also delete the App.config file, but there really isn’t much there to worry about. The use of the App.config in testing should be discouraged. If you’re having to put something in there then you have too much dependency on that. Keep in mind that the App.config in a test project should only include test configuration information. If it is using anything that is normally in the production configuration then you’ve got something you need to fix.

Creating the Core and Infrastructure Projects

Our next step is to create a project where we will keep the core logic of our application. This is business layer, but I don’t like that name because business logic often ends up getting mingled with infrastructure concerns. I am naming the next project Core to mean that this is central to the application. Only the things that are core parts of the application go here.

 05-NewProject-Core

 

 

So as usual I need to make a couple of modifications. First I delete the silly Class1.cs file and then move the Models from the web project and move it here. I would say that the domain objects that we are going to be dealing with deserve to be in our core application.

 06-SlnExpl-MoveModels

 

The Infrastructure is the next step. If you expect to have multiple infrastructure concerns that you want to separate into separate libraries go with a more specific name for this project. Since I expect to only deal with database concerns I will stick with a generic name> If I ever need to change things I am not too concerned since renaming things is actually really easy if I structure my application nicely and use refactoring tools to help.

07-NewProjectInfrastructure

Once I create this I will of course delete the Class1.cs file and I will end up with a pretty full Solution Explorer now. I’ve got most of the projects in place now. I could have started small here, but I know I am going to need these projects.

08-SlnExpl-CreatedInfrastructure

Creating the Unit and Integration Test Projects

Since I like to keep the unit and integration tests separated from the production code it is nice to keep them in a separate library. This means that the tests need not be included with the rest of the application in deployed scenarios. The only problem I can think of is keeping the tests in their own library could make them just another navigation headache. However, since I use ReSharper I have a navigation tool which allows me to quickly get to anything based on its name, so I am not concerned with that issue.

Since I am using MSTest for my testing framework I can use the Visual Studio Test template. If you’re using something else like NUnit you will just create a normal class library and include a reference to the NUnit dll.

09-NewProject-UnitTests

Since we created this from the UnitTest project template it added in the reference to the dll required to use MSTest. However, we will also need to eliminate these files which were created for us.

10-SlnExpl-DeleteTestProjFiles

The next step is an integration test library. These tests are very important in the project as they help us ensure that everything is working well together. We want all the individual pieces working, but knowing that they interact is just as important. We keep them separate because the integration tests can often be long-running and we want to be able to execute the unit tests first. They will run faster and if there are any issues we will know sooner. Creating the integration test project will be done the same way we created the unit test one.

11-NewProject-IntegrationTests

And as usual we have a few files that we do not need. Time to delete them.

12-SlnExpl-DeleteIntegrationTestProjFiles

 

 

I will soon discuss setting up the build process using NAnt and the continuous integration process using CruiseControl.net. As you may have noticed I think the structure of software projects and the initial setup are very important. Without build systems in place I think the development process can be very limiting.

 

ASP.NET MVC Beta Released

by Brendan Enrick Friday, October 17 2008 18:33

Just in case you missed the blog post from Scott Guthrie yesterday, I will post this.

Scott Guthrie's MVC Beta Announcement

ASP.NET MVC Beta Download

One of my favorite little added bonuses of using IDEs is that I get a lot of helpers that generate code and files for me. If I call a method that doesn't exist I am able to have a stub of the method automatically generated. In the ASP.NET MVC beta they've added a new menu for adding views.

The Add View window it brings looks extremely useful. I look forward to using that to create my views. It handles strongly-typed views and MasterPage selection.

Overall it looks like a nice release.

For those of you who want to deploy using ASP.NET MVC keep in mind that Scott says this in his post.

Today's ASP.NET MVC Beta release comes with an explicit "go-live" license that allows you to deploy it in production environments.  The previous preview releases also allowed go-live deployments, but did so by not denying permission to deploy as opposed to explicitly granting it (which was a common source of confusion).  Today's release is clearer about this in the license.

Good day and enjoy ASP.NET MVC's newest release.

Passing ViewData to User Controls in ASP.NET MVC Preview 4

by Brendan Enrick Thursday, July 24 2008 15:55

Yesterday I was upgrading an ASP.NET MVC site from Preview 2 to Preview 4. For the most part this is an easy process. Some assemblies needed to be updated and some information updated in the web.config file. Route declaration changed, but the same information is still required, so updating that was pretty easy. The released documentation and examples clearly show these changes. I also had to make the change to my controller actions so that they return ActionResults instead of being void methods. Again, this is a fairly simple task.

There was an adjustment to user controls which caused some problems though. Yasir and I were working on this task together so we could both learn about the preview 4 changes in MVC. We scoured articles looking for this information, and we tried many different changes to the user control.

Our problem was that we could not get access to the ViewData. ViewData in the user control was always null. It was quite annoying. Eventually in desperation after reading articles and release notes and not finding what we were looking for, we started reading the source code for MVC. We took a look at this file, which is the one containing the extension method we were calling in the .aspx files. System.Web.Mvc.UserControlExtensions This file contains the extension method RenderUserControl, which our code used.

The .aspx code we were using

<%
   =Html.RenderUserControl("~/Views/Shared/MyUserControl.ascx", ViewData, new { DisplayTitle = "Hello World!" }) 
%>

RenderUserControl calls this method called DoRendering

private static string DoRendering(ViewUserControl instance, ViewContext context, object controlData, object propertySettings) {
            ViewPage dummyPage = new ViewPage();
            dummyPage.ViewContext = context;
            dummyPage.Controls.Add(instance);
            dummyPage.InitHelpers();

            //set the properties

            SetUserControlProperties(instance, propertySettings);

            if (controlData != null) {
                instance.ViewData.Model = controlData;
            }
            else {
                instance.ViewData = context.ViewData;
            }

            //Render it

            string result = HtmlExtensionUtility.RenderPage(dummyPage);

            return result;
        }

In my haste to find a solution, I didn't read the code very carefully. All I noticed was exactly how to solve our problem. I discovered that the controlData parameter we were passing to this method was being assigned into instance.ViewData.Model. I didn't even read the next couple of lines which gave away the real answer. We went and added in the .Model to our code so that it could access the ViewData. The ViewData we were passing was going into a property of the ViewData called Model, so we just used it. We went to our user control and we changed the code there. This felt really bad to us, but we went along with it.

Today I realized our error. I was thinking about the code we had looked at this morning, and I realized our mistake. I was wondering, "Why was it checking if control data was null? If it was null shouldn't ViewData.Model be null? That's our ViewData right?" That is when I realized what must have been after that.

We were not supposed to be using Model. We had some standard ViewData. No strongly-typed ViewData was being used. We were using an the standard ViewDataDictionary object and passing it to the user control. A ViewUserControl object (which is the class we were inheriting from) supports generics. It was at that time when I realized exactly what everything was being used for. The Model property and the controlData parameter are there for strongly typed ViewData. You can use boxing and unboxing or generics to pass strongly-typed data to your ViewControl. The parameter and the generic Model were added so that the ViewData property of the ViewUserControl would not be interfered with.

This solution the MVC guys use allows custom ViewData to be used without having to muck the ViewData property of the user controls. Since they added this extra piece it could be the generic one. So now I have gone and changed my code. I no longer pass the ViewData as was done in the past. It is now simply grabbed from the context of the page. I pass a null value instead of passing in any controlData to the RenderUserControl method. It wires everything up for me now.

<%=Html.RenderUserControl("~/Views/Shared/MyUserControl.ascx", null, new { DisplayTitle = "Hello World!" })%>

As a reminder to everyone. Open source code means that you can go look at the code. If you are not sure how something works, just go read the code. It is freely available on CodePlex. You can look at how everything is working and get a much better understanding of the inner workings of the technology.

Creating a Simple Hello World Application Using MVC

by Brendan Enrick Thursday, December 27 2007 20:25

So I am finally sitting down to play with the ASP.NET MVC Framework. I've installed Visual Studio 2008 on my machine. You can obtain a 90 day free trial of Visual Studio 2008 from Microsoft if you don't own a copy. There are also Express Editions of Visual Studio 2008.

After installing Visual Studio 2008 I installed the ASP.NET 3.5 Extensions Preview. It contains the required components to use the new MVC Framework. Now that you have it installed open up Visual Studio and create a new project. Choose the web section and select ASP.NET MVC Web Application. I named my project "HelloMvc".

 NewProjectHelloMvc

Here you can see the files currently in this empty project. Notice there are a bunch of files that it comes with including a Controller and a couple of Views.

 HelloMvcEmptySolution

So now run the application by pressing ctrl + F5. You'll see this page once you run the application.

HelloMvcStartingPage

Fairly simple for now, but hey it works. Now we should try to figure out how to create a simple static page. We'll make it look kind of like that about view that is already in there. We want it to be hello. OK, so click on the About Us link in the application. You'll be at a URL similar to this one http://localhost:64701/Home/About. So as a nice test try changing "About" to Hello in the address bar. You'll receive this nice error message which tells us the first step in creating our Hello World page.

 HelloMvcActionNotFound

Ok so we need to define an action in our controller. The Home part of our URL is saying we want to use the HomeController, so open up that file in the Controllers folder and add the following code into that file.

[ControllerAction]
public void Hello()
{
    RenderView("Hello");
}

Notice that all we needed to do here is to use the ControllerAction attribute for a method we define. We'll defined the method named Hello by added a line calling the RenderView method. Congratulations you've defined your first Controller Action. So we now refresh the page where we previously received an error message, and we're greeted with a new one. So we are on the right track.

 HelloMvcViewNotFound

Now we need to create the view that we are trying to call in our Controller Action. So we'll right click on the Home folder inside of the View folder and select Add then New Item. Here is where Microsoft has tried to trick you. They've now changed how you attach to MasterPages. Instead of picking a Web Form and checking a box you now have a new choice Web Content Form. Make sure you pick that or you'll not get a MasterPage added for you. It will look like this.

 HelloMvcAddNewView

So now that we have that empty view we can quickly add a nice message into it. So go ahead and type in some html like the following.

<h2>Hello World! MVC is here!</h2>

Now you need to go into the code of this view and place in the following.

using System;
using System.Web;
using System.Web.Mvc;

namespace HelloMvc.Views.Home
{
    public partial class Hello : ViewPage
    {
    }
}

Notice here that we need to inherit from the ViewPage class instead of the System.Web.UI.Page class. We are instead using the System.Web.Mvc.ViewPage class. This will allow our .aspx page to work as a view. Make sure to build the application and then open up the view again in the browser. Woohoo you've successfully created an MVC Controller Action and a View. And as some icing on the cake we will now add a link to our view on the MasterPage so that we can easily access this Hello View whenever we want to.

Open up the Site.Master file. It is located in the \Views\Shared. You will see an unordered list in the html. There are currently two list items in the list; Home and About Us. You will want to add a new one using the following code.

<li><%= Html.ActionLink("Say Hello", "Hello", "Home") %></li>

Now refresh the page. From anywhere on this site you can now get to the Hello World View. The method we used here took 3 arguments. The first is the text which appears for the link, the second is the name of the view, and the third is the name of the controller. The following is our final product. We have the Hello World page as well as a nice link to it.

HelloMvcHelloView

Enjoy creating simple MVC Views!