Reputation: 2703
I have a base class
public class BaseQuestionBlock
{
public string Name { get; set; }
public string Description { get; set; }
//more props
}
And I have several view models that inherit from this, for example:
public class DefaultQuestionBlock : BaseQuestionBlock
{
public string SomeProp{ get; set; }
}
Finally I have a class that contains a List:
public class MyViewModel {
public List<BaseQuestionBlock> MyQbs{ get; set; }
//More props
}
I have a View where I render
@Html.EditorForModel(); //my model is MyViewModel
Inside the MyViewModel.cshtml i have the following:
@Html.EditorFor(m => m.MyQbs)
Everything displays properly using the views for each model. I have a custom model binder that correctly handles converting the posted qb's into their correct classes and I have a nicely populated view model on HttpPost.
I want to add modes to this process (e.g. New, Edit and Admin modes). My Model will stay the same but the view will change. I currently have 1 view per inherited question block. So, I have a DefaultQuestionBlock.cshtml and maybe a SpecialQuestionBlock.cshtml.
I would like to have an EditDefaultQuestionBlock.cshtml, NewDefaultQuestionBlock.cshtml, and a AdminDefaultQuestionBlock.cshtml.
Using the existing conventions in MVC is there a way to force what template to use?
I was thinking of that perhaps I could set the UIHint at runtime somehow on the instance of the DefaultQuestionBlock but that doesnt seem possible.
I know I can easily add a Mode property to the base model, set that when I instantiate the class and then in my DefaultQuestionBlock.cshtml view add if (mode == MyModes.Edit)
type logic but I think this clutters my view with business logic. I would rather have two separate views.
I know if I were to use EditorFor on a single Question block I could pass in the template at runtime but, I don't know how I can do this on a List:
@Html.EditorFor(m => m.DefaultQuestionBlock, "EditDefaultQuestionBlock")
I realize I could also have multiple view Models (e.g. AdminDefaultQuestionBlock, EditDefaultQuestionBlock) and then have a view that corresponds to each of these but that seems a bit overkill since the model properties don't change across the modes just the security on them.
Upvotes: 2
Views: 567
Reputation: 1023
I am still finding my way around this as well, but right now I would use an @Html.Action that returns different partial views depending on the user's role/security privileges. If you generally always have three 'roles', for instance, you could use a naming convention that allows you to return a viewname that appends a code so you can return something like
return PartialView("_DefaultQuestionsBlock" + Mode);
Upvotes: 1
Reputation: 239270
There's not going to be a conventions-based way unless you go ahead and implement those view models for each "mode", which I agree seems like overkill. However, you can always just manually specify what template it should use. For example:
@Html.EditorForModel("~\Views\Shared\EditorTemplates\AdminDefaultQuestionBlock.cshtml")
Obviously, you can put the template wherever you like. I'm also not sure how much of the path is actually required there, so I went ahead and went safe and specified the whole thing. You could perhaps get away with as little as "AdminDefaultQuestionBlock"
if it's in just the right location for Razor to be able to find it based on the context it has. You can play around with it.
Upvotes: 1