I'm very new to ASP.NET MVC so I hope my question makes sense. I'm using POCO objects as my model. It's my understanding that when the form is submitted MVC can create a new instance of my business object and fill the properties from the form automatically.
I use dependency injection so I create new instances using code like the following:
DependencyResolver.Current.CreateInstance(Of IBusObject)
How can I get ASP.NET MVC to call this method instead of trying to create a new instance by using the "new" keyword on the concrete class?
Looking at the MVC source code it will not use dependency resolution when creating an instance of the model type, so you can't get what you want out of the box, but you could easily achieve what you want by creating your own model binder which is DependencyResolver aware.
You could write a custom model binder deriving from the default model binder and override the CreateModel method to supply your custom instance.
Related
Just some idea to make more use of custom model binder. I am currently still using IMapper interface to do so, though wondering whether part of the purpose of custom binder is to mapping view model or input model to business entity? I can see there might be some limitations if i use MVC custom binder. What is the advantage to use the custom binder in MVC? Will my app gain better performance?
Short answer would be No, you should not
ModelBinder by itself is part of ASP.NET MVC infrastructure. If you would take a look at ASP.NET MVC pipline (PDF) you would see that it's job is
to convert a posted web form data (a string basically) or query string from URL to an instance of particular class.
ASP.NET MVC framework has a DefaultModelBinder that
is suitable for 99% of cases. Custom model binders could be used in situations where standard data conversion fails e.g. mapping $ 1,234.56 from a textbox to a decimal value of 1234.56
Moreover ModelBinder implements IModelBinder interface with a single BindModel() method. This method expects parameters that would be hard to 'hand-craft' to make any use of them and are totally not relevant to your scenario.
What you are realy looking for is
- either custom object mapping between viewmodels and business objects where you manually assign one object property values to another
- or taking advantage of libs/frameworks such as Automapper or ValueInjecter which take care of object mapping hassle away from you
- or a mix of both
I did MVC 2 two years ago. I am now using MVC 4 and would like to confirm a few things.
1) In MVC 4, we do not need to create a ModelMetadata class to annotate with data annotations for data validation. We may simply annotate the model classes themselves.
In other words, if we are using the EDM generator to generate a model and corresponding classes for us, then we may create a new set of partial classes with the same names and use data annotation attributes on those partial classes themselves.
We do not need to create a new type of model metadata class and decorate that class with data annotation/attributes, like here: http://www.asp.net/mvc/tutorials/older-versions/models-%28data%29/validation-with-the-data-annotation-validators-cs
2) For data annotations to work, we need a reference only to System.ComponentModel.DataAnnotations and not to Microsoft.Web.Mvc.DataAnnotations.
3) We do not need to instantiate the default model binder in the Application_Start event in the Global.asax file.
Could you please confirm if my understanding is correct?
As I remember, there's no difference between MVC 2 and MVC 4 when it comes to this. You didn't have to use MetadataType in MVC 2, you could have used partial classes for generated models.
I'm not able to find any MSDN doc on Microsoft.Web.Mvc.DataAnnotations, but for data annotations to work with MVC you'd need System.ComponentModel.DataAnnotations and System.Web.Mvc (it contains some additional attributes like HiddenInputAttribute).
No, you don't, it's instantiated by framework.
Actually, for question 1, you need to use Metadata classes to annotate the properties of of model-first EF classes in the same way as previously with MVC2. When you use code-first EF classes, you can annotate them directly - the annotations will be used for generating the database as well as for scaffolding the Views.
I am writing an area for administering several subsites, almost all of the functionality will be the same across each site (add/edit/remove pages etc) and my repository on instantiation takes the SiteIdentity so all the data access methods are agnostic in relation to this. The problem I have at the moment is trying to make my action methods also agnostic.
The URL pattern I want to use is along the lines of:
"ExternalSite/{identity}/{controller}/{action}/{id}"
A naive approach is to have each action take the identity parameter, but this means having to pass this in to my repository on each action as well as include it in the ViewData for a couple of UI elements. I'd much rather have this something that happens once in the controller, such as in its constructor.
What is the best way to do this? Currently the best I can come up with is trying to find and cast identity from the RouteData dictionary but part of me feels like there should be a more elegant solution.
It sounds like you want to use OnActionExecuting or a Custom ModelBinder to do that logic each time you have a specific parameter name (also known as a RouteData dictionary key).
Creating a custom modelbinder in ASP.NET MVC
Creating an OnActionExecuting method in ASP.NET MVC, Doing Serverside tracking in ASP.NET MVC
You have access to your route values in Request.RequestContext.RouteData, so you can make base controller and public property SiteIdentity, in such case you can access it from all actions in all inherited controllers.
I would like to set values for the ViewBag in a custom class I have created to handle my viewstate (for want of a non WebForms word!). I am aware that ViewData is a property of Controller base. Is there a way I can access the ViewBag from my class? .. another thought, as I want to do this in a class which is being auto-generated by the model binderr, is it possible to accomplish this by implementing a custom binder?
Regards.
I have an ASP.NET MVC App, where I have interfaces for each viewmodel.
On a view called /Product/Details/50 I can edit details for product with id = 50.
I use strongly typed views, with the type being IProduct. I use Castle Windsor to do DI. When I post the edit form on the /Product/Details/50 view, the IProduct instance defaults to what it was set to on the HttpGet method called Details(int id) in the same controller.
I guess it's something to do with modelbinding. If I change the HttpPost method Details(IProduct product) to Details(Product product) it seems to work fine.
Any ideas?
The issue here is that when we encounter IProduct, we don't know which type to instantiate. Our model binders don't integrate with your DI container. For the most part, I agree with Charlino, your domain models should probably be interface based, but the objects you model bind to ought to be dumb simple POCO objects which represent the values posted in the form.