Provide explicit view names when unit testing a controller action? - asp.net-mvc

Stephen Walther recommends that you should provide explicit view names when you want to unit-test them.
I definitely want to test them, but I'm curious whether or not this recommendation is still valid with the release of 1.0.
In the NerdDinner tutorial the tests just check if the viewResult is null. They don't explicitly specify the viewName, which is therefore empty.
I would like to remove the view-names provided as strings in the actual code, but these checks seems less useful to me though...
(I can't even think of a scenario where the viewResult does return null?!)

There are really two separate questions here. The first is whether or not anything has changed in the MVC framework since Stephen Walther wrote the recommendation which would change the recommendation. The answer to that question is "no."
The second question is whether or not the recommendation is a good practice. I'm going to disagree with Stephen Walther, here. His example is a bit strange. His unit test for the "Index" action attempts to assert that the action returns an explicit view name, when clearly it does not. If I wrote this unit tests, I would instead assert that the view name is equal to empty string. Then the unit test would pass. Instead of asserting that the action specifies a view of a certain name, a unit test would then effectively assert that the action specifies that the view have the same name as the action. This is a legitimate thing to test.
One of the guiding principles behind the MVC framework is convention over configuration. In other words, you should not be required to specify anything which is just the usual default value. The default value of the view name is the same as the action name. The documented behavior of the WebFormsViewEngine is to look for a view with the same name as the action unless a separate view name is specified. Not specifying a view name, therefore, is the same as specifying "use the default view name."
Therefore, I do not think it is a good idea to specify a view name which is the same as the default, and I do not think that using unit testing is a good reason to violate this convention.

Providing explicit view names matters if controller can return various views. Then you can unit test controller, that it returns one it's supposed to return by name. Otherwise - i don't see the point of using them.

Related

What is the difference between Dynamic and Strongly Typed Views in ASP.Net MVC

I got a url http://www.asp.net/mvc/overview/views/dynamic-v-strongly-typed-views
they create a not strongly typed view but at they refer #model dynamic at top of the view.
but rest of the code looks like normal strongly typed view. anyone can tell me what is the difference between Dynamic and Strongly Typed Views in MVC.
When one should use dynamic view. discuss with example when dynamic view is required ?
The difference is that a dynamic view won't enforce compile-time type-checking (binding to properties etc). You can name and bind any property you want. At run time, if it can't find it in the model, that's when you'll get an error. It's the same as the dynamic keyword in the language.
As to why or when to use it, generally speaking, don't. It's a workaround. Write a wrapper class, write the DTO, write an adapter, there's plenty of ways to make a strongly typed object to bind to. Implement an interface or something.
Rarely you might come across a situation where it's just not feasible (legacy code, 3rd party libraries?) to do it the "right" way. That's when you might be stuck with it. Run time errors are not fun to try to recover from - try to never use dynamic views.
The only time I personally have used it was to mock up test layouts and I didn't want to actually create full models yet. I'd not use it for production code.

Why use instance variables to "connect" controllers with views?

This is a conceptual question and I haven't been able to find the answer in SO, so here I go:
Why instance variables are used to connect controllers and views? Don't we have two different objects of two different classes (Controller vs Views). So, when the view is rendered we are in a different context, but we are using instance variables of another object? Isn't this breaking encapsulation in somehow?
How does Rails manage to do that matching from one object to another? Does it clone all the instances variables of the controller to the view?
In a sense, you could say that it is breaking encapsulation. I have found that if you are not careful, it is easy to get your business/presentation logic mixed together in Rails. It usually starts when I am writing a view template, and discover that I need some value which I didn't pass from the controller. So I go back, and tweak the controller to suit what I need in the view. After one tweak, and another, and another, you look at the controller method, and it is setting all kinds of instance variables which don't make sense unless you look at the view to see what they are for. So you end up in a situation where you need to look at both controller and view to understand either, rather than being able to take one or the other in isolation.
I think that using instance variables (together with the Binding trick) is simply a way to pass whatever values you need from controller to view, without having to declare parameters in advance (as you would when defining a method). No declarations means less code to write, and less to change when you want to refactor and reorganize things.
Rails uses eval and Binding to pass controller instance variables to views. See this presentation from Dave Thomas, there's a small example at minute 46' that explains how this is done.

How to write test case for mvc action filters?

I have an action filter which i got from the below link
http://blog.wekeroad.com/blog/aspnet-mvc-securing-your-controller-actions/
there is something called "RequiresAuthenticationAttribute"
for this i need to write test case.
how can i do this? form some of the blogs i read that we need to mock httcontext.
How can i mock this? what is the procedure that i need to do? is there any link for this?
Don't use the [RequiresAuthentication] attribute from Rob's blog. It's meant for a very old pre-release version of MVC. Use the in-box [Authorize] attribute instead.
Since the [Authorize] attribute is written by the MVC team, you don't need to unit test its logic. However, if you want, you can verify that it's applied to your controllers or actions. Simply get the Type or MethodInfo you're interested in, then call its GetCustomAttributes() method to get instances of AuthorizeAttribute. You can inspect those instances for the values that you expect.
If you want, you can look at the source code of AuthorizeAttribute for information on writing your own filter. Additionally, you can look at the official unit test of this type, so if you do end up writing a filter you can use a similar method to write your own type's unit tests.

ASP.Net MVC Controller Namespace array

I noticed that the MapRoute extension includes an overload that accepts a string[] parameter which is called 'namespaces'. I read what Google had for me on it, and supposedly this is to help the framework find controllers in places it wouldn't otherwise look.
I did some spiking, and tried putting controllers in weird locations. I put one in the Scripts folder; I even built one in a separate assembly with a separate root namespace.
Without putting anyting in the namespaces param, everything worked fine. If I put just one of the namespaces in the namespaces param, it still found all my controllers. I thought maybe it would use that array to disambiguate between similarly named controllers, but that didn't happen either. A HomeController in MyProj.Controllers and one in SomeOtherName.Stuff would collide still.
So my question is, is that parameter deprecated? Or is it still used somehow in a way that I have yet to discern?
Ok, so after further testing, I figured out that it is not a filter, exactly, but it kinda is also. I gave you 'answer' credit even though you're partially wrong.
So, it does, after all, act like I thought it should which is to say it disambiguates. Basically, the logical flow is something like this:
Look for a namespace in the _cache that matches one in the namespaces array
if that's found, look for a controller of the right name
-- if that's found, return it
-- if it's not found, return search everywhere else that it'd normally look
if it's not found, search everywhere lese
So, in short, my thought that the namespaces array would serve to disambiguate was correct. The reason my first test in that regard failed is that it only does a perfect match, and I made the mistake of using just the root n/s from the assembly (in other wordss, MyRoot instead of MyRoot.Controllers).
What this namespaces thing allows, then, is to have a HomeController in two different namespaces and match them differently depending on the url or params.
No, the value is not deprecated. It is used in DefaultControllerFactory.cs. Note that if the value is supplied, it completely replaces the standard name spaces searched. When the parameter is not supplied, the name spaces searched our determined by:
HashSet<string> nsDefaults = new HashSet<string>(ControllerBuilder.DefaultNamespaces, StringComparer.OrdinalIgnoreCase);
When the parameter is supplied, the list you supply replaces this value.
In either case, DefaultControllerFactory calls:
GetControllerTypeWithinNamespaces(controllerName, nsDefaults);
...with the list, either the one you supplied, or the default. So it is clear that the value is supported.
When you look at the source code there, and in ControllerTypeCache, you can see the real purpose of the namespaces value: It does not cause the controller factory to look in places that would not otherwise look; rather it is a filter. In other words, it prevents the default controller factory from looking and name spaces that it would otherwise search for controllers.

What should the view file/directory structure be in ASP.NET MVC?

I'm confused with how views are organized, and it is important to understand this as ASP.NET MVC uses conventions to get everything working right.
Under the views directory, there are subdirectories. Inside these subdirectories are views. I'm assuming that the subdirectories map to controllers, and the controllers act on the views contained within their subdirectories.
Is there an emerging expectation of what types of views are contained within these directories? For instance, should the default page for each directory be index.aspx? Should the pages follow a naming convention such as Create[controller].aspx, List[controller].aspx, etc? Or does it not matter?
View directory naming and file naming are important, because the ASP.NET MVC framework makes certain assumptions about them. If you do not conform to these assumptions, then you must write code to let the framework know what you are doing. Generally speaking, you should conform to these assumptions unless you have a good reason not to.
Let's look at the simplest possible controller action:
public ActionResult NotAuthorized()
{
return View();
}
Because no view name has been specified in the call to View(), the framework will presume that the view filename will be the same as the Action name. The framework has a type called ViewEngine which will supply the extension. The default ViewEngine is WebFormViewEngine, which will take that name and append an .aspx to it. So the full filename in this case would be NotAuthorized.aspx.
But in which folder will the file be found? Again, the ViewEngine supplies that information. With WebFormViewEngine, it will look in two folders: ~/Views/Shared and ~/Views/{controller}
So if your controller was called AccountController, it would look in ~/Views/Account
But there might be times when you don't want to follow these rules. For instance, two different actions might return the same view (with a different model, or something). In this case, if you specify the view name explicitly in your action:
public ActionResult NotAuthorized()
{
return View("Foo");
}
Note that with WebFormViewEngine, the "view name" is generally the same as the filename, less the extension, but the framework does not require that of other view engines.
Similarly, you might also have a reason to want your application to look for views and non-default folders. You can do that by creating your own ViewEngine. I show the technique in this blog post, but the type names are different, since it was written for an earlier version of the framework. The basic idea is still the same, however.
In regard to expected names for the views, I think that it's one of those things that each project or organization will try to standardize.
As you hinted to in your question, it's possible that some of these Views (or more precisely, the Actions that render them) become popular across the board, like for example the ones below that are common in RoR applications that adopt the REST paradigm:
/orders/ (i.e. index)
/orders/show/123
/orders/edit/123
/orders/update/123
/orders/new
/orders/create
/orders/destroy/123
The choice/standardization of the Views is largely dependent on how you model your application (to say the obvious) and how fine-grained you want to go. The closer you map your controllers to individual model classes (cough...resources...cough), the shorter your actions will tend to be and more easily you will be able to follow a standard set of actions (as in the above example).
I also believe that shorter actions help pushing more and more of the model business logic into the models themselves, where it belongs.

Resources