Creating a model for MVC - asp.net-mvc

I'm building my first MVC project and I have a question about the model.
Each webpage can only contain 1 model, yet my page will require 2 models, one is the search option (the ability to narrow your search such as selecting price range, colour etc) as well as the data.
Is it really as simple as creating a new Model, similar to a ViewModel which in this case would only have 2 properties, a SearchModel and a ProductModel?

Yes, there are really two "models" which is sometimes confusing. There's the "View Model" and the "Domain Model." The view model is passed directly to and from the view. The domain model describes the real-life domain that you're dealing with and is what the database persists. Often, they are the same thing, such as if you're displaying information for a single real domain object (e.g., a car). If you have two domain models that go on one page, you should make a view model with both as properties.

If you are looking to have two models in a view then this question might provide useful information:
multiple-models-in-a-view
Edit:
A good example is the 'Manage' view in the default 'Account' controller of a fresh mvc app. It uses a partial view to handle the changing of a user's password. Whilst both views are using the same model type it shows how to implement a partial view. In this case both the main view and the partial are submitting to the same method on the controller, hence they need to use the same model (which is a parameter for the controller method). But if the partial were to invoke a different controller method then the submitted model could be different. Hope this makes sense :)

Related

Editing only a partial model in ASP.Net MVC

I'm quite new to MVC, and stumbled on a problem. I've googled a lot but couldn't find a solution.
I'm using ASP.Net Membership with roles.
Lets say I have a model of a product with attributes:
Name
Art no
Category
How can I implement this so different roles cab only be allowed to edit parts of the object?
(Let's say one role cannot change the category of a product, for example.)
Is it possible to have different Views for the same Model or different Models for the same object?
If I leave out some of the properties, they will have NULL value when I save them.
I tried using #HTML.HiddenFor(...) but then the validation for those fields failed.
A ViewModel sounds like it would do the trick. For all but the most trivial of scenarios, you will get into problems when you tightly couple the Model and the View.
If you havent used them before, a ViewModel is simply a class (model) for the specific view you are rendering. You can customize required properties and validation on the ViewModel and then bind it to the Model, so the structure is most more flexible and easy to work with.
There is a detailed intro at ViewModels http://kazimanzurrashid.com/posts/asp-dot-net-mvc-viewmodel-usage-and-pick-your-best-pattern
EDIT
You could then have a ViewModel for each of the role, although if you are only looking to protect a property from being updated by certain roles there should be other solutions such as setting the html input to disabled and then testing on the server that the category value is still in its original state (note you should always perform such a test as the Post request can be altered).

in asp.net mvc what's a clean way to create an entity from the 'create' view of another entity?

I am trying to come up with a clean design for this -
I am using MVC to process orders, so I have an 'order' entity, with its own controller and views.
From the Create Order view I would like the user to add a 'Customer' entity. I have a controller and CRUD operations for 'customer'.
When someone creates a new Order I would like them to either
1) enter a customer name to see if that customer already exists, and if so, add that Customer to the Order, or
2) Create a new Customer then add that new Customer to the Order.
My problem is I am not sure of a good way to access the Customers from within the Order.
-do I create a partial view for Create Customer, then use that view in the Customer Create AND Order Create?
-then would I create a partial view 'SearchCustomers' that passes params to an action on Customer controller and that returns results? Would I be able to reuse this across the site?
You can see I am not sure about a few things - are partial views the way to reuse things? can partial views be reused across controllers and access different controllers from the ones theyre in?
I have gone through an MVC book and online tutorials but they all seem to use beginner examples, where Model objects don't contain other Model objects.
Thanks for help
Views never "access controllers".
The flow is:
Controller Action Method -> Creates View Model -> Hands it off to a View -> View displays it -> View can pass sub-models on to other partial views
Decomposing everything into smaller models and partial views (or using Editor templates) is a good approach. You can then assemble those smaller models into a larger view model for a complete page, or you can use the ViewBag to assemble them in a non-strongly typed manner.

Returning ad-hoc view models from ASP.NET MVC2 Controllers

I'm porting an existing system to ASP.NET MVC2. In the current legacy app, the user can select from dozens of available fields to customize CRUD forms for different entities in the domain model, similar to the way ERP systems allow customization of core modules.
My question: I'm looking for a good pattern or example for this kind of behavior in ASP.NET MVC2. It seems to me it's rather like creating a ViewModel dynamically based upon user choices, or perhaps the right approach is data-driven view pages that aren't strongly-typed where I can reflect over the results client-side to determine field headings or something -- if that makes sense :). Or maybe I can drive AutoMapper or similar dynamically # runtime based on user choices?
The underlying domain model is EF4-based and I'm using a simple Repository pattern # present for the ViewModel.
TIA for any input! Michael
If I didn't find anything else that matched the needs and went on to do it custom, I would:
Use the ViewModel with all the fields / not just the ones the user picked.
Pass both the ViewModel and the view configuration to the view
Call some html helper that for each item in the configuration adds a field with the corresponding property in the model
The configuration could be passed as either part of a containing ViewModel or in a separate entry in ViewData
Depending on what you need, building/passing the view configuration could be put in an Action Filter. Alternatively the helper could pull it directly.
A different approach is if you need completely custom fields. I mean user defined fields. If that's the scenario, that's not typed at the controller level already, so I'd pass the list of fields/values to the view. The view can do a foreach on those adding the fields. Again that could be moved to a HtmlHelper.

RenderPartial and Dynamic Selection of Partial Views

My MVC application contains a parent model, which will contain 1 or more child models.
I have set up the main view to display properties from the parent model, and then loop through a collection of my child models (of various types, but all inheriting from the same base type). Each of the child models have a corresponding partial view.
My "parent" view iterates over the child models like this:
foreach (ChildBase child in ViewData.Model.Children)
{
Html.RenderPartial("Partials/"+child.ChildType.ToString()+"Child",
section);
}
My application has the appropriate /Partials/ChildType1.ascx, ChildType2.ascx, etc. Everything works great.
Is this an appropriate way to use Partial Views? It feels slightly off-kilter due to the dynamic names, but I don't know another way to perform dynamic selection of the proper view without resorting to a big switch statement.
Is it advisable to use the same view for multiple "modes" of the same model? I would like to use the same .ascx for displaying the "read only" view of the model, as well as an edit form, based on which Controller Action is used to return the view.
Iconic,
It's difficult to answer the questions without knowing exactly what you're trying to achieve.
I'll have a go though:
If you're familiar with web forms, think of your partial view as a webforms usercontrol for the moment and think of the part of your model that is relevant to your partial views as a 'fragment of information' that want to pass across to the partial view.
Natural choices for using a partial view would be for elements used in many views across your site.
So ... in answer:
1.Although what you are doing is valid, it doesn't seem quite correct. An example of a partial view I have used might be a row in a grid of data where you'd call the partial view passing in the row object as its model:
foreach (MyObject o in Model.objects)
{
Html.RenderPartial("Shared/gridRowForObject.ascx", o, ViewData);
}
You can strongly type your views also to expect a specific type to be passed through as the Model object.
Again another use might be a login box or a 'contact me form' etc.
2._Ultimately this is a personal design decision but I'd go for the option that requires the least application/presentation logic and the cleanest code in your view. I'd tend to avoid writing to many conditional calls in your view for example and by inferring a base type to pass across to all of your partial views as in your example, may well tie you down.
When learning the MVC framework I found the Oxite code to be useful.
I hope that helps.

ModelFactory in ASP.NET MVC to solve 'RenderPartial' issue

The 'RenderPartial()' method in ASP.NET MVC offeres a very low level of functionality. It does not provide, nor attempt to provide a true 'sub-controller' model *.
I have an increasing number of controls being rendered via 'RenderPartial()'. They fall into 3 main categories :
1) Controls that are direct
descendants of a specific page that
use that page's model
2) Controls that are direct
descendants of a specific page that
use that page's model with an
additional key of some type.
Think implementation of
'DataRepeater'.
3) Controls that represent unrelated
functionality to the page they appear
on. This could be anything from a
banner rotator, to a feedback form,
store locator, mailing list signup.
The key point being it doesn't care
what page it is put on.
Because of the way the ViewData model works there only exists one model object per request - thats to say anything the subcontrols need must be present in the page model.
Ultimately the MVC team will hopefully come out with a true 'subcontroller' model, but until then I'm just adding anything to the main page model that the child controls also need.
In the case of (3) above this means my model for 'ProductModel' may have to contain a field for 'MailingListSignup' model. Obviously that is not ideal, but i've accepted this at the best compromise with the current framework - and least likely to 'close any doors' to a future subcontroller model.
The controller should be responsible for getting the data for a model because the model should really just be a dumb data structure that doesn't know where it gets its data from. But I don't want the controller to have to create the model in several different places.
What I have begun doing is creating a factory to create me the model. This factory is called by the controller (the model doesn't know about the factory).
public static class JoinMailingListModelFactory {
public static JoinMailingListModel CreateJoinMailingListModel() {
return new JoinMailingListModel()
{
MailingLists = MailingListCache.GetPartnerMailingLists();
};
}
}
So my actual question is how are other people with this same issue actually creating the models. What is going to be the best approach for future compatibility with new MVC features?
NB: There are issues with RenderAction() that I won't go into here - not least that its only in MVCContrib and not going to be in the RTM version of ASP.NET-MVC. Other issues caused sufficent problems that I elected not to use it. So lets pretend for now that only RenderPartial() exists - or at least that thats what I've decided to use.
Instead of adding things like MailingListSignup as a property of your ProductModel, encapsulate both at the same level in a class like ProductViewModel that looks like:
public class ProductViewModel() {
public ProductModel productModel;
public MailingListSignup signup;
}
Then get your View to be strongly-typed to the ProductViewModel class. You can access the ProductModel by calling Model.productModel, and you can access the signup class using Model.signup.
This is a loose interpretation of Fowler's 'Presentation Model' (http://martinfowler.com/eaaDev/PresentationModel.html), but I've seen it used by some Microsoft devs, such as Rob Conery and Stephen Walther.
One approach I've seen for this scenario is to use an action-filter to populate the data for the partial view - i.e. subclass ActionFilterAttribute. In the OnActionExecuting, add the data into the ViewData. Then you just have to decorate the different actions that use that partial view with the filter.
There's a RenderPartial overload I use that let's you specify a new ViewData and Model:
RenderPartial code
If you look at the previous link of the MVC source code, as well as the following (look for RenderPartialInternal method):
RenderPartialInternal code
you can see that if basically copies the viewdata you pass creating a new Dictionary and sets the Model to be used in the control. So the page can have a Model, but then pass a different Model to the sub-control.
If the sub-controls aren't referred directly from the main View Model, you could do the trick Marc Gravell mentions to add your custom logic.
One method I tried was to use a strongly typed partial view with an interface. In most situations an agregated ViewModel is the better way, but I still want to share this.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IMailingListSignup>" %>
The Viewmodel implements the interface
public class ProductViewModel:IMailingListSignup
Thats not perfect at all but solves some issues: You can still easily map properties from your route to the model. I am not shure if you can have a route parameter map to the properties of MailingListSignup otherwise.
You still have the problem of filling the Model. If its not to late I prefer to do it in OnActionExecuted. I dont see how you can fill a Model in OnActionExecuting.

Resources