Best practices for debugging ASP.NET MVC Binding - asp.net-mvc

Can you give me any general advice on how to debug ASP.NET MVC Binding?
When everything works as expected, ASP.NET MVC is great. But if something does not, like something doesn't bind for some unknown reason, I find it hard to trace down the problem and find myself spending hours tracking down a seemingly simple problem.
Let's imagine you land in a controller method like this:
[HttpPost]
public ActionResult ShipmentDetails(Order order)
{
//do stuff
}
Let's further imagine that the Order class looks like this:
public class Order
{
public decimal Total {get; set;}
public Customer Customer {get; set;}
}
public class Customer
{
public string Name {get; set;}
public string Phone {get; set;}
}
What are good places to start when Order in the controller method is not bound correctly? What are good places to start when only parts of the Order are bound correctly?

Although #russ's answer is useful and will sometimes be necessary, both options seem a little low level when the main question is more about the big picture. Thus, I'd recommend Glimpse.
From its about page:
… Glimpse allows you to debug your web site or web service right in the browser. Glimpse allows you to "Glimpse" into what's going on in your web server. In other words what Firebug is to debugging your client side code, Glimpse is to debugging your server within the client.
And since you've specifically asked about data binding, you'll want to look at the binding tab documentation. You'll be able to see, again from the docs:
Ordinal: Order in which the MVC Model Binding infrastructure attempted to bind the available data
Model Binder: Model Binder that was used in a given scenario
Property/Parameter: Name of the thing that the Binder was trying to bind
Type: Type of the thing that the Binder was trying to bind
Attempted Value Providers: Providers that the Binder attempted to use to get a given value (and whether it was successful)
Attempted Value: The actual value that the provider has to work with (post type conversation, etc.)
Culture: The culture that was used to parse the raw value
Raw Value: The raw value that the provider has to work with (pre type conversation, etc.)
See the quick start. Briefly:
Install the glimpse.mvc3 package
Go to http://yourhost/yourapp/Glimpse.axd and "turn it on."
Click on the glimpse icon on the bottom right of any view in your app for details.

As Darin has suggested, start with inspecting what is being sent from the client to the server using something like Firebug, Fiddler, or other web debugging proxy tool.
Failing that, you might want to step through the source code to see what's happening during binding.
Two ways that I can recommend doing this are
Include the System.Web.Mvc source code project in your application and reference this. This is good for learning but probably not recommended for a commerical application.
Download the symbols for System.Web.Mvc from the Microsoft Symbol servers, change your settings to be able to debug framework source code and set a break point appropriately to step through.

In my case looking at the ModelState property in the controller method provided the answers why the modelbinding was failing.

A good place to start is download and install FireBug and see what gets posted from the client to the server. Then you will see what's missing, incorrect, ... Blog posts such as Model Binding to a List are good reads as well to get acquainted with the proper syntax that the default model binder uses.

From Visual Studio side:
Set a breakpoint on entry to your endpoint.
Open the Immediate via the Debug menu option.
Type in ModelState.Keys.ToList()
This will show the binding errors by name/key.
Better yet type in ModelState.Values.ToList()...

Put a breakpoint in your controller-method and make a watch for Request.Params to see what is actually coming in to the controller in terms och parameters.

Related

ASP.NET WEB API Multiple Interfaces

I am designing ASP.NET WEB API service with two interfaces. First interface is read-only and second one is admin interface (to be used with MVC app) with full CRUD support. Does anyone know where I can get more information on such setup, any tutorials, walk thought, sample design document?
Also does it worth splitting these into two interfaces or keep them in same? But problem is that in read-only I expose 2-3 properties for every object while for admin there are 10-15?
Similar setup for WCF or design spec will do.
If I understand what your wanting to do, may I suggest rather than having one URL, i.e. \dataStuff\dataView split off into another view, maybe \dataStuff\edit\ which only admin's have access to, can be done like so:
[Authorize(Roles = "Administrators")]
public ActionResult edit()
{
return View();
}
then next to each data element that your viewing add the following to ONLY admin's through use of User.IsInRole
#foreach (var item in Model.dataTable)
{
#*
write a value from the data table here
*#
#Html.ActionLink("edit", "edit").If(User.IsInRole("Administrators"))
<br/>
}
obviously you don't have to display your data like this, I'm just showing that you add to the end of each element of the database an edit ActionLink IF the user is admin.
This allows your admin to view data like a user and also have the added functionality they need. Code re-use is better than a single view which has two states, Admin and non Admin.
Sorry if this isn't the best explanation, fairly new to MVC
Seems like this concept is sometimes called CQRS.
Sample: http://martinfowler.com/bliki/CQRS.html

Is it possible to get the controller and the action (NOT THEIR NAME!!) based on the url?

I have found a dozens of threads about getting the name of the controller and method based on the url, I managed that just as well. Can I get the MethodInfo of the method based on their name automatically from the MVC engine, or do I have to do Type.GetType("Namespace.Controllers."+cname+"Controller").GetMethod(mname)? Which is not so nice, since how do I know the namespace in a framework class? How do I know if the default naming patterns are being observed, or is there a different config in use?
I want to get a "What Would MVC execute?" kind of result....
Is it possible?
EDIT: further info:
I have a framework which uses translatable, data-driven urls, and has a custom url rewriting in place. Now it works perfectly when I want to show the url of a news object, I just write #Url.Content("~/"+#Model.Link), and it displays "SomeNewsCategory/SomeNews" instead of "News/29" in the url, without the need to change the RouteTable.Routes dynamically. However in turn there is a problem when I try to write RedirectToAction("SomeStaticPage","Contact"); into a controller. For that, I need to register a static link in db, have it target "/SomeStaticPage/Contact", and then write
Redirect("~/"+DB.Load(linkid).Link); and that's just not nice, when I have 30 of these IDs. The web programmer guy in the team started registering "fake urls", which looked like this:
public class FakeURL
{
public string Controller;
public string Action;
public int LinkID;
}
and then he used it like Redirect(GetFakeUrl("controller","action")); which did the trick, but still was not nice. Now it got me thinking, if I apply a [Link(linkid)] attribute to each statically linked method, then override the RedirectToAction method in the base controller, and when he writes ReturnToAction("action","controller"), I'll actually look up the attribute, load the url, etc. But I'm yet to find a way to get the methodInfo based on the names of the controller and the action, or their url.
EDIT: I've written the reflection by myself, the only thing missing is getting my application's assembly from inside a razor helper, because the CallingAssembly is the dinamically compiled assembly of the .cshtml, not my WebApplication. Can I somehow get that?
To answer your edit, you can write typeof(SomeType).Assembly, where SomeType is any type defined in code in the project (eg, MvcApplication, or any model or controller)
Also, you can write ControllerContext.Controller.GetType() (or ViewContext) to get the controller type of the current request EDIT That's not what you're trying to do.
I found out that it was totally wrong approach. I tried to find the type of the controller based on the name, when instead I had the type all along.
So instead of #Url.Action("SomeAction","SomeController") I'll use #Url.MyAction((SomeController c)=>c.SomeAction()), so I won't even have to find the controller.

What is "posted" in ASP.NET MVC applications?

As I review more code and blog posts from lots of MVC sources, I still haven't wrapped my mind around what is "posted" when a request is made. I realize MVC doesn't support post, but I'm having trouble finding resources that can explain it well enough to understand.
Inside the controller's public ActionResult nameOfAction(what the heck goes here?) { ... } what are my parameters?
Sometimes it looks like Visual Studio scaffolds (int id, MyObject myobject) for an Edit-style action--it includes something from my model, but not always.
Sometimes, it's (int id, FormCollection collection) for a delete-style action. Why not use the modeled object here? Is a FormCollection object always "posted"?
Sometimes, I see (RouteInfo routeInfo) which isn't recognized in my MVC2 Intellisense (is this MVC1 only or something?)
How can/do/should I establish these parameters? I think this will help me a lot at design time.
What gets post back from a form in MVC is the form data which includes each form element in a keyvalue pair.
If you only need this information then you would use:
public ActionResult nameOfAction(string name, string lastName, string etc)
MVC has some smart data model binding which takes the form data and automatically creates an object which is part of you domain model. For instance it could automatically create a Person object with the provided form data.
I believe there is a security concern with this as a user of your site may post data which is not part of your form and guess what your models are to inject their own data.
I dont think this is a massive issue though and this is the way I would go.
I think you can use the anti-forgery helper to prevent users from posting back data which is not allowed in a form. anti-forgery
Use strongly typed views with a view-model and the strongly typed helpers. Then when you POST, you should get an instance of that view-model out.

ASP.NET MVC: Best practices for keeping session state in a wizard-like app

Let's say I have a Web application implemented like a set of wizard pages to edit a complex object. Until the user clicks on the "Finish" button, the object doesn't get saved to the back-end system (a requirement), so in the meantime I have to keep the whole information about the object in some kind of a session state.
Also, some of the wizard pages have to show combo and list boxes with potentially large number of items. These items are fetched from the back-end system using a Web service.
Coincidentally, the wizard allows the user to freely jump from one wizard page to any other (using tab links on top of the form), so it's not a simple "next, next... finish" thing.
Additional constraint: the Web application runs on a Web farm and the customer is weary of using server-side session state. In the best case they want to keep the size of the session state minimal (they had problems with this in the past).
So basically there are two problems here:
How/where to keep data entered by the user in the Wizard?
Whether to cache the combo/list items received from the back-end and if so, where?
Options I'm considering:
Storing the object in a WebForms-like ViewState (by serializing it into the HTML page). This would also include the combo box items. Obviously, there could be a problem with HTML pages becoming very large and thus Web application will be slow.
Storing it into server-side session state, regardless of the customer's wishes and without knowing how the performance will be affected until it is tested on the actual Web farm (late in the project).
I cannot decide between the two. Or is there another alternative?
Why cache at all? You could just have the tabbed pages where each page is a div or panel and just display the current div relating to your tab. That way you dont have to keep track and process all the inputs when the user submits the form.
Is it possible to store the wizard data in a temporary table in the database? When the user finishes the wizard the data is copied from the temporary table and deleted. The temporary table includes a timestamp to remove any old uncompleted data.
As Daisy said, it doesn't have to be cached. You could also use hidden form fields. Because these could map to the same object on each controller action, you could progressively build the object through successive pages.
//Here's a class we're going to use
public class Person
{
public int Age {get;set;}
public string Name {get;set;}
public Person()
{
}
}
//Here's the controller
public Controller PersonCreator
{
public ActionResult CreatePerson()
{
//Posting from this page will go to SetPersonAge, as the name will be set in here.
return View();
}
public ActionResult SetPersonAge(Person person)
{
//This should now have the name and age of the person
return View(person);
}
}
//Here is your SetPersonAge, which contains the name in the model already:
<%= Html.Hidden("Name", Model.Name) %>
<%Html.TextBox("Age") %>
And that's pretty much it.
I can suggest a few more options
Having the entire wizard as a single page with the tabs showing and hiding content via javascript on the client-side. This may cause the the initial page to load slower though.
Caching the data at the server using the caching application block (or something similar). This will allow all the users to share a single instance of this data instead of duplicating across all sessions. Now that the data is lighter, you may be able to convince the customer to permit storing in the session.
There is a lot of resistance in the MVC community against using Sessions. Problems are that a lot of us developers are building login systems like a bank website. One could argue for hidden fields and that works for some situations but when we need to time a user out for security and compliance, then you have several options. Cookies are not reliable. Relying on Javascript timers are not reliable and are not 508 compliant as the goal should be to degrade gracefully. Thus for a Login, a Session is a good option. If you write the time to the client browser, to the server database or server file system, you still have to manage the time per user.
Thus use Sessions sparingly, but don't fear them. For the wizards, you technically can serialize hidden fields passing them around. I suspect the need and scope will become much greater and an authorization/authentication implementation with Sessions will be the crux of the application.
If you cannot use ajax (for validation & dropdowns and ability to convert wizard to tabbed page) and cannot use html5 (for dropdown caching and form state saving in local storage), then I think you are pretty out of available "best practices" and you have to resort to bad (or worse) one.
As MVC is opponent of WebForms regarding session usage, maybe you can use a workaround? For example, besides storing all these values in some temporary database records you need to clean up later, you could set up AppFabric extension for Windows Server and use it to store dropdown list items (and scope can be for all users, so if more users are using system at the same time you need only one call to web service to refresh cache), and also to temporary store your objects between steps. You can set your temporary objects in AppFabric to automatically expire so cleanup is not necessary. It can also be of help for speeding up other parts of your system if you extensively call another system over web services.
I've been dealing with the same issue and, while my requirements are a little simpler (keeping state for just a few strings), my solution may work for you. I'd also be interested in hearing others thoughts on this approach.
What I ended up doing is: in the controller I just dump the data I want into the Session property of the Controller and then pull it out next time I need it. Something like this for your situation:
//Here's the controller
public Controller PersonCreator
{
public ActionResult CreatePerson()
{
//get the age out of the session
int age = (int)(Session["age"]);
//do something with it...
return View();
}
public ActionResult SetPersonAge(Person person)
{
//put the age in the session
Session.Add("age", person.Age);
return View(person);
}
}
The thing I like about this is I don't have to put a bunch of hidden params around on my view pages.
The answer to this can be found in Steve Sanderson's ASP.NET MVC 2/3, and requires a reference to the MVC Futures assembly. This link to Google Books is exactly what he does.
In essence, you serialize the wizard data to the View. A hidden field is rendered storing all of the acquired information.
Your controller can work out what to do through the use of the OnActionExecuting and OnResultExecuted (to cater for redirects) to pass it to the next view.
Have a read - he explains it much more thoroughly than I can.

ASP.NET MVC Response Filter + OutputCache Attribute

I'm not sure if this is an ASP.NET MVC specific thing or ASP.NET in general but here's what's happening. I have an action filter that removes whitespace by the use of a response filter:
public class StripWhitespaceAttribute : ActionFilterAttribute
{
public StripWhitespaceAttribute ()
{
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
filterContext.HttpContext.Response.Filter = new WhitespaceFilter(filterContext.HttpContext.Response.Filter);
}
}
When used in conjunction with the OutputCache attribute, my calls to Response.WriteSubstitution for "donut hole caching" do not work. The first and second time the page loads the callback passed to WriteSubstitution get called, after that they are not called anymore until the output cache expires. I've noticed this with not just this particular filter but any filter used on Response.Filter... am I missing something?
I also forgot to mention I've tried this without the use of an MVC action filter attribute by attaching to the PostReleaseRequestState event in the global.asax and setting the Response.Filter value there... but still no luck.
This KB article may offer some insight into the root cause of this issue. While the filter 'breaks' caching in IIS6 it throws an error in IIS 7. This seems to be a design / test-time improvement at best.
UPDATE
Here's an official "answer" from MS Dev Support on this issue.
Question:
What is the alternative to response filtering in ASP.NET for modifying HTML rendered by another process when:
1. The other process cannot be modified
2. Post-cache substitution must be supported
Answer:
"Yes, you question is clear as blue sky and this is officially claimed to be not support. As Post-cache substitution would combine certain substitution chunks to the response bytes while response filtering expects to filter the raw bytes of the response(not modified). So the previously combined substitution chunks cannot be preserved anymore.
There is not an alternative from Microsoft so far."
AFAIK, the problem is that the action filters doesn't get executed if the request goes to the output cache. The AuthorizeAttribute works around this problem by calling some obscure Output Cache API. However, I don't think that is the best solution for what you're are trying to do.
You should be working with output cache, not around it. What you should be doing instead is making sure that the spaces are removed from the response before it gets stored in the output cache.
Update
It seems that attaching a filter, no matter what filter, disables the WriteSubstitution functionality as you suspect. I've tried following the trail in the HttpResponse class using reflector but I can't find any proof that confirms this suspicion. I think the answer lies within the HttpWriter class.
Another Update
It so happens that I'm currently reading the excellent book "Pro ASP.NET MVC Framework" by Steve Sanderson (buy it if you don't already have it). In chapter 10 he links to a post on his blog where he talks about partial output caching and the poor integration between the MVC framework and the output cache. I haven't tried the custom outputcache attribute in the post yet... I will try it out and let you know if it does anything to solve the problem.

Resources