PrimeDigit – A Design Blog by Will Shaver

January 28, 2009

MVC RC1

Filed under: ASP.Net,c# — Will @ 11:05 am

As I’m sure you noticed, MVC RC1 is out now. In reading through the release notes I found this:

“The overloads for DropDownList and ListBox helper methods were reworked to fix various usability problems that were reported by customers.”

Thanks for listening!

December 24, 2008

GAC Conflicts with ASP MVC

Filed under: ASP.Net,c# — Will @ 10:04 am

By some strange combination of beta and pre-release candidate installs I managed to create some serious conflicts with ASP.NET MVC. Thereby producing this wonderful little error:

Compiler Error Message: CS0433: The type 'System.Web.Mvc.FormMethod' exists in both 'c:\WINDOWS\assembly\GAC_MSIL\System.Web.Mvc\1.0.0.0__31bf3856ad364e35\System.Web.Mvc.dll' and 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\06c0b3cf\32bec25d\assembly\dl3\71bfb65b\e11bf5c5_9e55c901\System.Web.Mvc.DLL'

I am using my own build of the source from codeplex so that I can debug through it to improve my knowledge of the codebase. From research online it looks like the assembly version between the latest pre-release and the beta weren’t incremented, or the web-runner tries to look in the GAC before the /bin, or the evil garden gnomes are at it again, or Microsoft wants to punish me for building THEIR dll files.

To solve this problem, i opened up the AssemblyInfo.cs files of the Mvc project and upped the AssemblyVersion to 1.0.0.9. Then hacked my web config to use that version. As I’m running in debug mode, and can’t sign the assembly I also had to remove the PublicKeyToken from the reference.

<add assembly="System.Web.Mvc, Version=1.0.0.9, Culture=neutral"/>

And suddenly we’re back in business.

September 9, 2008

ModelStateDictionary and ParameterBinding

Filed under: ASP.Net,c# — Will @ 11:14 am

I laid this out in more detail on the forums here:
http://forums.asp.net/p/1317154/2610342.aspx#2610342

I thought I’d mention it to this group so that people were aware of this difference between the interaction the old ParameterBinders and Rescues in version 4 and the new ModelBinders and HandleErrorAttributes of version 5.

The new way of doing parameter binding expects all errors to be placed into the ModelStateDictionary specified in the GetValue method.
public override object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState) {

The ModelStateDictionary can then be checked in the controller for errors via ViewData.ModelState.IsValid

I think the idea is that multiple binding errors can then be reported to the user at one time:
foreach (var value in ViewData.ModelState.Values)
{
value.Errors…..
}

Unfortunatly our current NameValueDeserializer that is used by the DeserializeAttribute throws exceptions when it encounters errors. These exceptions are NOT caught by Rescues / HandleErrorAttributes. The ControllerActionInvoker (in preview 5) calls

IDictionary parameters = GetParameterValues(methodInfo);

before the try/catch block that passes off errors to the HandleErrorAttributes. So if you’re using any kind of attribute deserialization and expecting your exceptions to be displayed all pretty like in your rescues… then move line #177 to line #180 of your ControllerActionInvoker.cs :)

-Will

February 7, 2008

Unit Testing Framework for MS MVC.NET

Filed under: ASP.Net — Will @ 11:04 pm

The Pain – A Brief History of MVC.NET

Files: MvcTestingFramework.rar – or – MvcTestingFramework.zip

Back in November, ScottGu gave us some great examples on how to use the (then unreleased) MVC Framework. A major advantage of this framework is to be in the ease of testing. One of the classes used in that demo was a TestViewEngine that was implemented to determine what variables were passed to RenderView and RedirectToAction.

Since then we’ve learned that it was some private class that wasn’t in the framework. In December, Phil Hack recommended subclassing as a means to get at the RenderView which he admits leaves a certain bad taste in some people’s mouths.

I’m one of those people.

He also went on to explain that it can be done through mocking with RhinoMocks but then changed his mind saying that it wouldn’t build against the actual CTP version of the framework. (Thanks, you tease.) Then there was the concept of putting it in an extension method, but that prevents us from properly setting the stage for our tests.

There is also an issue with testing TempData in controllers even if you manage to get around the RenderView problems via subclassing. Ben Scheirman recommended doing this through mocking using SetupResult. Justice Gray then chimes in that something similar can be done for mocking Request.Form.

Seeing all this chaos, and knowing that there had to be a better way, I’ve combined a number of these recommendations into a framework that allows for easy and effective testing of ControllerActions.

It uses a bunch of Mocking, Reflection, and Dynamic Proxies to get the job done.

Sample Uses of the Framework

If you’re like me you’ve already downloaded the rar file at the top of the page. Please direct your attention to the MvcTestingFramework.Sample.Test project in the StarsControllerTest.cs file. Here’s you’ll find some simple uses of the framework.

Using RenderView


        [Test]

        public void ListControllerSelectsListView()

        {

            MvcTestHandler handler = new MvcTestHandler();

            StarsController controller = handler.CreateController<StarsController>();

            controller.List();

            Assert.AreEqual("List", handler.RenderViewData.ViewName);

        }

Note that we’re creating an instance of MvcTestHandler in this and every other test case in this class. This handler performs several functions, namely creating our Controllers and populating them correctly. We’re also able to get at the parameters used in the RenderView method call by our ControllerAction via the RenderViewData class.

Using Redirect To Action


        [Test]

        public void AddFormStarShouldRedirectToList()

        {

            MvcTestHandler handler = new MvcTestHandler();

            StarsController controller = handler.CreateController<StarsController>();

            controller.AddFormStar();

            Assert.AreEqual("List", handler.RedirectToActionData.ActionName);

        }

Again, we’re able to access the ActionName from the handler’s RedirectToActionData class.

Using Request.Form and TempData


        [Test]

        public void AddFormStarShouldSaveFormToTempData()

        {

            MvcTestHandler handler = new MvcTestHandler();

            StarsController controller = handler.CreateController<StarsController>();

            handler.Form["NewStarName"] = "alpha c";

            controller.AddFormStar();

            Assert.AreEqual("alpha c", controller.TempData["NewStarName"]);

        }

We simulate a form request, then read it back in from the controller’s TempData member. Do that with a controller that you make via a standard constructor and you won’t have such good results.

Comments on this Framework

The MvcTestingFramework relies on two great frameworks, the Castle DynamicProxy framework and the aforementioned RhinoMocks framework.

After establishing a proxy of the given controller, the existing RedirectToAction and RenderView methods are changed so that they save the parameters and don’t actually redirect or render a view.

One particular annoying part (and there were several, saved only by The Reflector) was that a couple of objects types used by RedirectToAction are marked as internal, so I was forced to iterate over the properties looking for the Action and Controller properties. MS… Please, no more hoops and lions.

The one area that I don’t have working is Session variables. (You’ll note those unit tests fail.) Hopefully someone more familiar with Rhino Mocks will be able to get this working.

December 11, 2007

LINQ EndsWith

Filed under: ASP.Net — Will @ 10:39 am

From the bottom of the Entity Framework Beta 3 docs on Query Execution, “The EndsWith method can also return different results because SQL Server considers two strings to be equal if they only differ in trailing white space, whereas the CLR considers them to be not equal.” That’s not exactly clear, so I spent some time trying out different scenarios.

Case One:

Database Field ColorName : ‘Blue   ’ // 3 spaces

SQL Query: … WHERE ColorName LIKE ‘%e   ’
Returns 1
SQL Query: … WHERE ColorName LIKE ‘%e’
Returns 0
SQL Query: … WHERE ColorName = ‘blue’
Returns 1
SQL Query: … WHERE ColorName = ‘blue   ’
Returns 1

LINQ Query … where c.ColorName.EndsWith(‘e’) select c;
Returns 0
LINQ Query … where c.ColorName.EndsWith(‘e   ’) select c;
Returns 0
LINQ Query … where c.ColorName.EndsWith(‘ ’) select c;
Returns 1
LINQ Query … where c.ColorName.Trim().EndsWith(‘e’) select c;
Returns 1
LINQ Query … where c.ColorName.Trim().EndsWith(‘e   ’) select c;
Returns 1

Case Two:

Database Field ColorName : ‘Blue’

SQL Query: … WHERE ColorName LIKE ‘%e   ’
Returns 0
SQL Query: … WHERE ColorName LIKE ‘%e’
Returns 1
SQL Query: … WHERE ColorName = ‘blue’
Returns 1
SQL Query: … WHERE ColorName = ‘blue   ’
Returns 1

LINQ Query … where c.ColorName.EndsWith(‘e’) select c;
Returns 1
LINQ Query … where c.ColorName.EndsWith(‘e   ’) select c;
Returns 1
LINQ Query … where c.ColorName.EndsWith(‘ ‘) select c;
Returns 1
LINQ Query … where c.ColorName.Trim().EndsWith(‘e’) select c;
Returns 1
LINQ Query … where c.ColorName.Trim().EndsWith(‘e   ’) select c;
Returns 1

So basically if you want to find a string that actually ends with a ‘ ’ using LINQ to Entities, best to use something other than EndsWith. This is certain to cause some major headaches for someone, so hopefully it gets fixed before the EF is out of beta.

December 7, 2007

Entity Designer CTP2 Comments

Filed under: ASP.Net — Will @ 12:37 pm

I’ve spent some time yesterday and today playing around with the new Entity Designer GUI and Framework. So far I’m impressed with the possibilities and bothered by simple things that could cause repetitive headaches. Here are a few suggestions that I’d offer to the Entity Designer team:

  • Ignore the sysdiagrams table when importing by default. Those of us who actually want this can check this box when we import the tables. SQL2005 is kind enough to hide it in the System Tables folder, please do something similar.
  • How do I view the XML code? The only time I can easily get access to it is when there is an error. I can’t view it by right clicking on the .edmx file. (Like one can with a Data Access Layer .xsd file.)
  • Return types of Navigation Properties are not displayed at all in the designer and difficult to ascertain without plowing through generated code.
  • Foreign key naming conventions are completely ignored for imported tables. Please don’t ignore them, or make it easier to see what they were.

To illustrate points three and four above, I’ve made myself a very simple database which might represent maternal genealogies, perhaps for someone studying Mitochondrial DNA.

As you can see, each person has a foreign key to another person who happens to be that person’s mother. Importing this into the Entity Designer via the wizard gives us two very cryptic columns called Person1 and Person2. Conceptually we might understand that each person has both a reference to her mother as well as a reference to all of her daughters. So one of these keys is a singular reference that we’d like to rename to “Mother” and another that we’d like to rename to “Children”. Examining these Navigation Properties in the designer shows:


Person 1


Person 2

Both of them have public getters and setters, both use the same Association, and neither of them list what type they return. To figure how to rename these, we must go to the generated c# code. (We can’t get to the xml code easily after all.)

So we can see from here that Person1 should be our Children/Daughters and Person2 should be Mother. Now we can rename these links appropriately.


Taking a look at a different example will illustrate my comment about ignoring foreign key names. This database is very simple with two tables as follows.

Importing this into the Entity Designer shows:

Now this is a bit easier than the previous problem to fix as the designer shows that the Association is liked to either “LastBrokenBy” or “LastFixedBy”. Is fixing all of these names part of the expected standard process of setting up the Entity Design?

Powered by WordPress