Editing only a partial model in ASP.Net MVC - 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).

Related

Creating a model for 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 :)

ASP.NET MVC ViewModel to Hold Lists & "Images or YouTube URL's"

I'm posting this question because I do not know the best/correct way of doing the following.
My team-mate (the designer) sent me a good looking design that includes a wizard for adding new items (for auction). The user has to fill in all the required details which include the title, description, starting price...etc AND a list of tags (up to 4 tags - chosen from the database, will use auto complete) as well as a list of up to 3 images/youtube url's (for the sake of better explanation check this image out: http://i55.tinypic.com/2v11zzr.png)
Ok so I figured out how I should do the wizard ( reference: how to make a wizard with ASP.Net MVC) but I'm not sure about how to collect the lists and the images/url's. Here's what I'm thinking:
For the images/url's, I should create a parent view model from which two sub-classes (ImageViewModel & YoutubeUrlViewModel) would inherit from and then in the controller action when I parse the post data, I would check to see the instance of the parent view model and act accordingly.
Now about the lists, I'm not sure whether I should include a List in my view model or whether I should include 4 string properties representing the tags (the same will apply to the list of images/url's).
So what's the best way of doing this?
And Haacked to the rescue: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
:)

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.

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.

When to use a Presentation Model in ASP.NET MVC?

Imagine a blog engine in ASP.NET MVC where I want strongly-typed Views. I have a Model for BlogPost and a Model for Comments. A typical page would display a blog post and all of that post's comments. What object should I pass to the View()? Should I create a Presentation Model? Maybe I'm using that term incorrectly, but by that I mean should I create a composite model just for a View(), something like BlogAndComments? Should my controller create an instance of BlogAndComments and pas that?
Or, should I somehow pass both a BlogPost and Comments object to the View?
I think you're on the right track with your understanding of Presentation Models. As to when you should create a View Model, the answer is probably 'it depends'. In your example, you can probably get away with passing the BlogPost and Comments in the ViewData object. It's not gorgeous, but hey, it gets the job done.
When and if that starts to feel ugly or unwieldy, then I would start thinking about making a View Model. I usually end up with the notion of some sort of 'Page', which includes the page title, common data, and then specific stuff for a particular page. In your case, that might end up as a BlogViewPage, which includes Title, BlogPost and List comments.
The nice thing about that approach is that you can then test that controller by making a request and testing the BlogViewPage to ensure that it contains the expected data.
In my opinion comments belong to the view as much as the post itself.
Make a BL class for your comments like:
class CommentBO
{
Guid UserID;
string Text;
}
Then you have a BO for your post.
class PostBO
{
Guid UserID;
List<CommentBO> Comments;
}
Then your model can be really simple.
class BlogModel
{
string AuthorName;
string BlogTitle;
List<PostBO> Posts;
}
Pass it to the view and render it.
You may be tempted to omit all BO and just fill the model directly from the database. It is an option, but not exactly the right one. A model is just a package of things for a view to display. These things however should be prepared somewhere else, namely at the business logics level with just a nominal participation of the controller.
I always use strongly typed views and create a presentation model class for each view or view user control. The advantage is that by looking at the presentation model class alone I know exactly what are the values that the view uses. If I were passing domain models then that would not be obvious because domain models may contain many properties that the view does not use. I would have to look at the view's markup to figure out what values it needs. Plus the presentation model usually adds certain properties that are not available in the domain model. It seems a bit tedious but I think it saves time and makes the code better in the long run.
In my opinion if comments belong to a blog post why not create a collection of comments on the blog post model? That makes perfect sense from a domain modeling stand-point and chances are whatever ORM you are using would support lazy-loading that collection which simplifies your controller logic as well.

Resources