All viewmodels inherit from 'BaseViewModel', can I set this up in OnActionExecuting? - asp.net

If all my actions have a model that inherits from BaseViewModel, is it possible to initialize this model from the OnActionExecuting method?
Currently in all my actions I do this:
var model = new SomeModel();
model.User = Users.Get(...);
Now I am loading the user object in OnActionExecuting, so I was hoping I could setup my model from there somehow.

You can't do it in OnActionExecuting, since at that point you don't know which subclass of BaseViewModel to use. However, you can update the model in OnActionExecuted, which runs after the action method but before the view is rendered.
Most likely you are populating these properties to use in the view only, but if you do need access to them in the action method you can put them into ViewBag or a controller property in OnActionExecuting and add them to the model in OnActionExecuted

Related

ASP.NET MVC Register custom Model Binder for all ViewModels

I have created a Custom Model Binder that works perfectly.
All my ViewModels extend the BaseViewModel however when I register the Model Binder for BaseViewModel it just doesn't run.
If I register every ViewModel "by hand" like the following line it works perfectly
ModelBinders.Binders[typeof(ArticlesViewModel)] = new ContextDataBinder();
What I need to know if there is a way to do that kind of registration for all my viewModels without register all viewModels one by one.
As it was commented in my original post you can register all the model blinders by replacing the default binder
ModelBinders.Binders.DefaultBinder = new ContextDataBinder();
However that didn't worked for my specific case because the ViewModels that the framework creates automatically always return the previous ViewModel (in searches for example it doesn't return me filtered results but all the results).
I ended up creating a List of types containing the type of only the ViewModels that actually need to pass trough the ModelBinder and with a foreach e register them all one by one.

How to gain control of what is returned after a route matches?

With ASP.NET MVC, when a route matches, the framework will determine the Controller type and then use the ControllerActivator class to create a new instance of it and then execute the Action method and finally return it's result to the request caller.
Just out of curiosity, what if I wanted to intervene exactly between the route and the Controller. Let's say controllers don't fit my needs. Let's say I just need to execute a random method in a class and return it's result.
What would I do then? What would I have to override? Can you please provide the path? A sample code would be appreciated too.
Create your own controller factory which implements IController factory. Something like below.
public class MyControllerFactory : IControllerFactory
Implement IControllerFactory interface
Register your new controller factory in Global.asax Application_Start event.
ControllerBuilder.Current.SetControllerFactory(typeof(MyControllerFactory));
You can check code of DefaultControllerFactory as reference for implementing your own factory.

Asp.net mvc razor - Send data to main layout

I am newbie in asp.net mvc.
I created an asp.net mvc4 empty application and added an entity model to it.
I have a layout page which I want to display menu categories,header,footer vb.But how can I send the data contains one more entity object(last posts,categories,tags) to layout page ?
Thanks
If you want to pass data (coming from database I assume) to the layout view you are facing a scenario where you have data that is passed to every page in your application. So what I would do is create a base controller from which all your controllers will inherit:
public class BaseController : Controller
{
public LayoutModel model;
public BaseController()
{
// Here you will use some business logic to populate your Layout Model
// You might also consider placing this model into the cache to prevent constant fetching of data from the database on each page request.
model = _service.Populate();
ViewBag.LayoutModel = model;
}
}
As you can see I used the constructor of the base controller to fetch the data needed for your layout view. I made a property named model and used some business logic method called Populate (you need to write this yourself) to populate the model variable. Then I place the model into the ViewBag.
Once I have this set up then every controller I make in my solution needs to inherit from the base controller:
public class HomeController : BaseController
{
// Controller code here...
}
which means that every controller can now access the model property from the base controller.
From here you can use the ViewBag.LayoutModel on each view like this (declare a local variable at the top of the view and cast it into the underlying type):
#{
LayoutModel MenuModel = ViewBag.LayoutModel;
}
and then use it like this:
#MenuModel.SomeProperty
This is just one of the ways to do it but there are other less/more complex ways. You need to do some research on your own and see which technique fits you the best...

What's the best way to pass both a model and FormCollection data to my MVC 3 post controller

Normally, when receiving form data in a controller, I'd use:
public ActionResult Edit(int id, FormCollection formValues)
I have a view which is bound to a model but also includes some items not attached to the model which I thought I'd be able to access via FormCollection as
public ActionResult Edit(int id, MyModel objModel, FormCollection formValues)
I wondered if this is the best way to achieve this or if there's another to code this.
If this is a post, you will need to tag the method with the HttpPost attribute.
[HttpPost]
public ActionResult Edit(int id, FormCollection formValues)
{
var objModel = new MyModel();
// updates model here
TryUpdateModel(objModel);
}
In your view, you would have something like:
#model MyModel
... some html here
<fieldset>
<legend>MyModel Information</legend>
#Html.EditorForModel()
</fieldset>
So you can edit the model fields using the EditorForModel and retrieve those values using TryUpdateModel. Noting that you still have access to your FormCollection object.
This isn't the way to work. You shouldn't use your database model directly into your View.
You should pass a ViewModel. This way you can pass your model and extra properties.
public class MyViewModel
{
// All the properties for your model.
// All other properties needed and not attached to your model
}
In the Post action in your controller you can receive the MyViewModel and just make your model with the properties inside the ViewModel.
Check out this post for more information:
http://blogs.msdn.com/b/simonince/archive/2010/01/26/view-models-in-asp-net-mvc.aspx
Before you get any further, read about difference between a domain model and a view model. Quite often, in a simple application you can get away with using a domain model. As the system grows, you are likely to encounter problems where simple features will be difficult to implement. Eventually you'll see a need to refactor code and this is when you are likely to see a need for a view model.
Your question is regarding parameters that are passed to controller actions. You have a controller to edit something.
There is an Edit GET where you do something like this:
Read data from database
Wrap it into the object
Pass this object to a view which will display the object
There is an Edit POST want to recieve data and write changes to the database. So what do you need to make that happen? You need id and a combination of fields that you wish to update. Passing FormCollection and something else means that you have to map values from FormCollection to your domain model. This is time consuming and a repetative task.
You don't want to do this, so you want submit back a single object, doesn't matter whether it's a view model or a domain model, but it should be an object that contains all the data that you need for an update.
Data binding feature of the MVC 3 framework will automatically map fields from the form to your model using clever reflection.
What you are doing is kind of works and it's a great way to learn. So don't give up. Refactor, see whether you can pass a single object and work with that.
Good luck

Asp.net mvc 2 model binders what's behind scene

Im starting with MVC2 and i have a simple question:
If i have a typed view with a form inside, and this textbox created with lambda expressions:
<%: Html.TextBoxFor(e => e.Name)%>
When i submit this form the default model binder take the request form, takes the model typed to the view, serialize the data posted (as a this model) and pass it to an action of my controller.
To try to explain myself better, lets imagine that i have a url like localhost/edittestmodel/ID/1 and i have in my controller action the following code:
public ActionResult Edit(int id)
{
TestModel testmodel=new TestModel();
testmodel.Name="texttorenderintotextbox";
//whats the class that place the testmodel properties into the view?
return View(testmodel);
}
What's the responsable class for place the Name property of my testmodel object into the textbox
<%: Html.TextBoxFor(e => e.Name)%>
Thanks in advance.
Best Regards.
Jose.
It's the TextBoxFor helper method that's responsible for generating the input field from the lambda expression.
View's don't have anything to do in POST request and model binding
When you have strong type views, model type is barely used to have the simplicity of code intellisense in view's code (so you can use lambda expressions like in your example).
But when you POST data back, nothing gets checked against the view. It gets checked against controller action parameters though. And if there's a parameter with a certain custom model binder type, that particular model binder is used to process incoming data.
But to answer your question: TextBoxFor checks your strong type view's model and generates particular textbox with correct name attribute. So data from it will be posted back under the correct form field name.
To go even deeper. It's the view engine that parses view's ASPX code and runs all server side scripts including Html.TextBoxFor() call.

Resources