by Donovan Brown
30. September 2012 03:46
Problem:
I have changed the language of my browser but I am still only getting me default resources.
Solution:
Add the following line to your web.config as a child of the system.web element.
<globalization enableClientBasedCulture="true" uiCulture="auto" culture="auto"/>
Explanation:
While working on an ASP.NET MVC application I wanted to test my localized resource files. From the options of my browser I updated the language. However, when I viewed the page I continued to see the default values. Not until I added the globalization element to me web.config did my browser load the correct resources.
by Donovan Brown
23. September 2011 16:22
Problem:
I need to test an MVC Controller Action that needs the Identity of the current user without mocking the HTTPContext.
Solution:
Create a custom Value Provider that allows access to the current user via an Action Parameter.
Explanation:
One of the goals of the MVC pattern is making the application easier to test. Simply using the pattern does not grantee your application will be easy to test. The application must be designed with testing in mind. This does not require that you use Test Driven Development (TDD) but I do believe you must be what I like to call "Test Aware". You must constantly be thinking during your design how are we going to test this? Does this design lend itself to easy testing? Testing can no longer be an afterthought.
While recently working on a MVC project I ran into an issue that was going to be very difficult to test because it relied on the read only User property of the Controller base class. My goal was to find a way to allow my action to be tested without having to Mock the HTTPContext. The action I was testing required Authorization and used the User.Identity property to query information from the data store. Because the User property of the Controller base class is ready only I was unable to set it in my unit test which would require me to mock the HTTPContext to test that action.
MVC Controllers have several mechanisms for receiving data. You can access the data from context objects, invoke the framework's model binding feature or have the data passed as parameters using a value provider. I prefer my action methods to have data passed as parameters. When your action depends only on the parameters, without accessing context data directly they become much easier to understand and test. Actions that only depend on their parameter are called "Pure". When your action method accepts parameters the framework employs the help of a collection of Value Providers and Model Binders to locate suitable values. Like many components in the MVC framework Value Providers and Model Binders are pluggable. This flexibility in the MVC framework allows developers to replace or extend the framework. My solution was to simply create a custom Value Provider that would allow me to access the current user as an input parameter to my action method.
Below is an example of the way the action would be written if you access the User property of the Controller base class.
[Authorize]
public ActionResult Index()
{
Models.Userdetails clerk = context.Userdetails.Where(u => u.Username == User.Identity.Name).Single();
return View(context.Citations.Where(c => c.ID == clerk.ID &&
string.IsNullOrEmpty(c.UploadedBy)));
}
However, to test this method would be very difficult. Instead I decided to write my action method so that it accepts a GenericPrincipal object as a parameter.
[Authorize]
public ActionResult Index(GenericPrincipal currentUser)
{
Models.Userdetails clerk = context.Userdetails.Where(u => u.Username == currentUser.Identity.Name).Single();
return View(context.Citations.Where(c => c.ID == clerk.ID &&
string.IsNullOrEmpty(c.UploadedBy)));
}
By writing the method this way I was able to create my test method without having to mock anything.
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
// Act
GenericIdentity id = new GenericIdentity("userName");
GenericPrincipal user = new GenericPrincipal(id, null);
ViewResult result = controller.Index(user) as ViewResult;
// Assert
ViewDataDictionary viewData = result.ViewData;
Assert.IsTrue(viewData.Model is IEnumerable<Models.Citations>);
}
To achieve this design I had to extend the Value Providers with a custom class.
Writing a custom Value Provider is very simple. You simply create a class that implements the IValueProvider interface. The IValueProvider interface only has two methods:
• ContainsPrefix - This is your value providers way of letting the MVC framework know you can handle this item.
• GetValue - If you return true from ContainsPrefix this method will be called to provide the value.
To allow the MVC framework to access your value provider you must provide a ValueProviderFactory class as well. This class derives from ValueProviderFactory and simply returns an instance of your Value Provider. The code below shows both the Value Provider Factory and the Value Provider.
public class CurrentUserValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
return new CurrentUserValueProvider();
}
private class CurrentUserValueProvider : IValueProvider
{
public bool ContainsPrefix(string prefix)
{
return "user".Equals(prefix, StringComparison.OrdinalIgnoreCase);
}
public ValueProviderResult GetValue(string key)
{
return ContainsPrefix(key)
? new ValueProviderResult(HttpContext.Current.User, null, CultureInfo.CurrentCulture)
: null;
}
}
}
The final step is to register your Value Provider Factory with the MVC framework. Add the highlighted code to the Application_Start method inside Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ValueProviderFactories.Factories.Add(new Classes.CurrentUserValueProviderFactory());
}
This adds your custom Value Provider to the MVC framework and allows you to gain access to the current user in any action method by simply having a GenericPrincipal user parameter.
by Donovan Brown
22. December 2010 19:58
Problem
I am struggling to learn MVC 2.
Solution
Get a copy of "Pro ASP.NET MVC 2 Framework, Second Edition". It is also offered in a Kindle version.

Review
Having had a lot of success with Web Forms and the data bound controls I really had a hard time when I first looked at MVC. I felt I was taking a step back in time to classic ASP. The lack of all the creature comforts of Web Forms was hard for me to justify. Also with the incredible suite of test tools from Microsoft Visual Studio Ultimate I was able to test my sites to ensure a high level of quality so I dismissed MVC about a year ago as a fad.
After the release of MVC 2 and hearing of plans for MVC 3 I realized it was not a fad. I also work with companies all over the world and would ask teams their impressions of MVC to see what I was missing. While at one client I was shown a very impressive Scrum Task Board written using MVC and was thinking to myself that would have been very difficult to do using Web Forms so I decided to give it a second look.
While searching for books to aid in my learning I ran across Pro ASP.NET MVC 2 Framework, Second Edition and have been very happy with the amount of great information in this book. Once you get past his Web Form bashing it is a great book and I recommend it for anyone trying to learn MVC.
I must say that now I "get it" I am very fast a cranking out new functionality for a current project http://proTableSports.com. Now with MVC 2 and .NET 4.0 I don't feel I have lost like I did in the past. I was able to use all the Membership, Role and Profile providers that I was used to in Web Forms. With the addition of jQuery all my client side code is also easier to write.
I don't recommend books lightly. I am certain you will enjoy this one.
715aef18-ae89-498d-8a5e-c6d86cf7bfe4|1|5.0
Tags: MVC
Work
by Donovan Brown
19. December 2010 20:33
Problem
When I enable Client side Validation on my MVC 2 view the validation error messages are showing as soon as the page loads even if everything is valid.
Solution
Define the styles to hide content until an error is detected.
Code
/*----------------------------------------------------------
ASP.NET MVC FRAMEWORK DEFAULT CSS CLASS NAMES
----------------------------------------------------------*/
.error,.field-validation-error{color:red}
.input-validation-valid,.field-validation-valid,.validation-summary-valid{display:none}
.input-validation-error{background-color:#fee;border:1px solid red; outline: none}
.input-validation-error:focus{outline:none}
input[type="text"].input-validation-error:focus, select.input-validation-error:focus{outline:none}
.validation-summary-errors{color:red}
.validation-summary-errors span{font-weight:700}
.validation-summary-errors ul{list-style:disc inside}
.validation-summary-errors ul li{font-weight:normal}
.validation-summary-errors ul li label, .validation-summary-errors ul li span{display:inline !important; font-weight:normal}
Explanation
When you enable client side validation the content of the error messages and validation summary are rendered to the screen with a class of *-valid. The class is changed to *-errors when a validation error is detected. If your style sheets does not hide the *-valid style sheet classes you will see that content when the page is display.
by Donovan Brown
19. December 2010 19:54
Problem
I am using a Form Collection in my [HttpPost] action of my controller and my ModelState.IsValid is not being set correctly for invalid input.
Solution
Add a call to UpdateModel or TryUpdateModel which will populate your model and fire the validation rules setting the ModelState.IsValid property correctly.
Code
In the incorrect implementation below ModelState.IsValid is always true.
[HttpPost]
public ActionResult EditProfile(FormCollection values)
{
ProfileCommon profile = new ProfileCommon();
profile = profile.GetProfile(User.Identity.Name);
if(ModelState.IsValid)
{
profile.DisplayName = values["DisplayName"];
profile.Save();
return RedirectToAction("Index", "Home");
}
else //Show validation errors
return View();
}
In the correct implementation below ModelState.IsValid gets set by the call to TryUpdateModel.
[HttpPost]
public ActionResult EditProfile(FormCollection values)
{
ProfileCommon profile = new ProfileCommon();
profile = profile.GetProfile(User.Identity.Name);
//Fill my model from the collection and validates it.
TryUpdateModel(profile, values);
if(ModelState.IsValid)
{
profile.Save();
return RedirectToAction("Index", "Home");
}
else //Show validation errors
return View();
}
Explanation
The built in server side validation for MVC 2 will only work if your action accepts the a Model object as a parameter. This causes MVC to create the model object and automatically map the incoming form input values to it. As part of this process, it will also check to see whether the DataAnnotation validation attributes for the model are valid. If everything is valid, then the ModelState.IsValid check within our code will return true.
When your action accepts a FormCollection this does not happen therefore, the DataAnnotation validation attributes are never evaluated and the ModelState.IsValid is never set. We can correct this issue by simply performing those steps ourselves. MVC 2 provides functions that we can use to do this (UpdateModel and TryUpdateModel). The difference is Update will throw if there is a validation error whereas TryUpdate will simply set the IsValid to false.
An added benefit of using the UpdateModel is that an empty model will be populated with all the values from the form collection for you.