In MVC do partial views inherit the models of their Parent views? - asp.net-mvc

I'm passing some data to a View from my controller, which I wish to display inside a partial view inside that View (don't ask, it's complicated). I know I probably shouldn't even be passing a model to a view that's inded for another view, but I've noticed that the partial view is actually inheriting the Model from the parenmt View:
public ActionResult Index(){
Person p = new Person
{
FName = "Mo",
LName = "Sep"
};
return View(p);
}
Then inside my Index View I have:
<h2>Index</h2>
#Html.Partial("_IndexPartial")
and Inside _IndexPartial I have:
#Model.FName
and this Prints "Mo".
Is this behaviour intended like that in WPF where child controls inherit the data context of their parent View? And is it considered bad practise to use this in your application?
Thanks.

Is this behaviour intended like that in WPF where child controls
inherit the data context of their parent View?
Yes.
I see you are not currently passing any model to the
Would it work to just inherit the layouts, and then not need to use the partial at all?
If you want to keep using it like you are, maybe just be more explicit about it, and pass the current model to the partial.
#Html.Partial("_IndexPartial", Model)
If you look at the source for Html.Partial(view):
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName)
{
return Partial(htmlHelper, partialViewName, null /* model */, htmlHelper.ViewData);
}
It is passing the model via htmlHelper.ViewData, you can access the model in the same way in your view with #{ViewData.Model}, but this is NOT a good practice.

You can pass the model into the partial view as a second parameter using the overload:
#Html.Partial("viewname", Model)
Nothing wrong with this approach IMO as its the whole point in strongly-typed views and the benefits they bring...

Related

Passing data from the controller to the view in asp.net

I'm currently developping a website on asp.net MVC 4.
I'm a bit confused about the different ways to pass data from the controller to the view.
First of all, if we have a list of objects users, what's the difference between passing this list to the view using:
return View(users);
and
ViewBag.users = users;
My other question is about the first solution.
If we use this solution, do we have to use this
#model IEnumerable<mydb.users>
in the View?
Or could we use for instance
#model IEnumerable<mydb.registrations>
I know it would be odd to use a different model in the view than what we've used in the controller, but VS doesn't seem to be bothered.
Thanls a lot for you answers
You can pass parameters as you want, but the best way is to make your own "view model" for each view.
public class UsersViewModel
{
public IEnumerable<UserViewModel> Users { get; set; }
public int UserCount { get; set; }
}
Then pass this view model back to the view:
var viewModel = new UsersViewModel();
// ...
return View(viewModel);
You can use Automapper tool to automatically convert your entities to viewmodels and back. It will look like this:
// in Global.asax.cs on Application_Start
Mapper.CreateMap<User, UserViewModel>();
Mapper.CreateMap<IEnumerable<User>, UsersViewModel>();
// in your action
var viewModel = Mapper.Map<UsersViewModel>(mydb.users);
Your view model will be created automatically, check automapper docs for more info. Good examples on Automapper usage are available in RacoonBlog.
ViewBag is a container. You can pass anything to the View using the ViewBag say it a string or class or whatever. You can use any no of ViewBags to pass to view from controller.
return View(users); here you have the list there and you can pass only one object as model from controller to view.
The reply to the second question you can receive the object Model to View using #model where we use the reference to a Object in particular which is generic. The controller helps in identifying what is being passed to the view. You can use it in further coding using Model in your View. ex: Model.Users

Alternatives to ViewData?

I'm pretty new to MVC, ASP.net, and, well, server-side scripting in general.
I was watching a tutorial video at www.asp.net/mvc where the person was explaining a template. He explained that the controller using viewdata to send information to the view.
Correct me if I'm wrong, but I believe it was used like this:
CONTROLLER: ViewData["PropertyName"] = value;
VIEW: <p><%= ViewData["PropertyName"] %></p>
Is this correct use?
What would be a better way to do it, instead of using ViewData, and what's bad about it?
There are very view situations that I would advocate the use of the ViewData collection for.
For the most part, I would use Strongly Typed Views with individual View Models for each View.
Rather than using the ViewData a better approach would be to create a new Model object and pass that to the View which is strongly typed to the Model.
Model (Models/MyModels.cs)
public class MyModel
{
public string PropertyName { get; set; }
}
View (View/My/Index.aspx)
<%# Page Language="C#" Inherits="ViewPage<MyModel>" %>
<p><%=Model.PropertyName %></p>
Controller (Controllers/MyController.cs)
public class MyController : Controller
{
public ActionResult Index()
{
MyModel model = new MyModel()
{
PropertyName = "My Property Name"
};
return View(model);
}
}
Html.Encode can be used like this:
<%=Html.Encode(someObject) %>
or this if you're using ASP.NET 4.0
<%: someObject %>
Justin is correct regarding ViewData usage, as well as using View Models (This is definitely the solution that will probably most fit your needs).
The Session is another option, but it can tend to be a slippery slope, but you did ask for alternatives.
ViewData is good for complete random data that you're not sure what you're going to need.
If you're constructing well-defined views you'll want to use Strongly Typed Views. These let your view inherit from a particular business object (or, more usefully, a ViewModel) to display the data. In this situation, instead of ViewData["SomeProperty"] you could have access to a strongly-typed Model member ie Model.SomeProperty.
Also, Html.Encode is meant to be put around data elements that repeat user-entered data. It is meant to prevent HTML injection.

ASP.NET MVC PartialView generic ModelView

I have an ASP.NET MVC application which I want to dynamically pick the partial view and what data gets passed to it, while maintaining strong types.
So, in the main form, I want a class that has a view model that contains a generically typed property which should contain the data for the partial view's view model.
public class MainViewModel<T>
{
public T PartialViewsViewModel { get; set; }
}
In the User Control, I would like something like:
Inherits="System.Web.Mvc.ViewUserControl<MainViewModel<ParticularViewModel>>" %>
Though in my parent form, I must put
Inherits="System.Web.Mvc.ViewPage<MainViewModel<ParticularViewModel>>" %>
for it to work.
Is there a way to work around this? The use case is to make the user control pluggable. I understand that I could inherit a base class, but that would put me back to having something like a dictionary instead of a typed view model.
You can use the DisplayTemplates and EditorTemplates to accomplish this. So if I'm reading your question right, you have a setup like this:
If you are using .NET 4.0 (yay for covariant generics!)
System.Web.Mvc.ViewPage<MainViewModel<object>>
If you are using .NET 3.5:
System.Web.Mvc.ViewPage<MainViewModel<object>>
public class MainViewModel
{
public object PartialViewsViewModel { get; set; }
}
You can then invoke DisplayFor on that object to get a partial view. So invoking:
<%= Html.DisplayFor(m => m.PartialViewsViewModel) %>
Will look for a template in your DisplayTemplates folder for a skin of the name of your type. So if you have a ParticularViewModel.ascx in your DisplayTemplates, it will use that control as the 'partial view'. If you were using some other kind of view model type, then search for OtherViewModel.ascx (for example).
The template for ParticularViewModel.ascx would then have:
System.Web.Mvc.ViewUserControl<ParticularViewModel>
Which lets you treat the object as a strongly typed model.

Reusable Content Box Data In ASP.NET MVC?

If I create a PartialView for a box that holds a header, image and content what is the best way to store the content without using a database?
Example: TurboTax
I doubt the content for the boxes in the sidebar are stored in a database but to make reusable code it would be beneficial to create the structure in a PartialView and populate the content areas. I can create a PartialView and pass a Model from the parent Controller to the PartialView but then I would be stuck copying and pasting that same content if I wanted to use the same box on another page.
For fixed content you might want to think about using XML+XSLT or even HTML snippets in the file system and simply rendering them. An HtmlHelper method might make more sense for this than a partial view - Html.RenderXml() or Html.Include(). The only real difference between these and partial views is that the view engine isn't invoked since there aren't any substitutions. I do this sort of thing with my privacy policy and terms and conditions. I'd certainly consider keeping these cached.
If these really are templates and you are just substituting content, then I think the partial view works well and I would consider putting the data in a database, again, maybe using caching if I found that performance suffered. You could use this in combination with the former -- say keep your images/xml in the file system and a pointer to them in the database so you know which ones to pick in the partial.
Passing data to partial view that is used in many places can be done in many ways:
Create base model class for all your models. In base class define PartialModel property which will be holding model for partial view (there may be many of them if use have many partial views). Now you can populate the PartialModel property in controller action, but to make code more reusable you can create your own Action Filter which will insert the partial view data just after the action method is executed (but before the model is passed to the view)
public class PartialViewModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
BaseViewModel model;
if (filterContext.Controller.ViewData.Model == null)
{
model = new BaseViewModel();
filterContext.Controller.ViewData.Model = model;
}
else
{
model = filterContext.Controller.ViewData.Model as BaseViewModel;
}
model.PartialModel = new PartialModel(...) // Partial model initialization
base.OnActionExecuted(filterContext);
}
}
Then you can use it like:
[PartialViewModel]
public ActionResult Index()
{
//...
}
Another option: you can create BaseController class for all your controllers and create PartialModel on base controller initialization. Then PartialModel can be stored in ViewData[] dictionary. Because using ViewData dictionary in views is bad, create extension method on HtmlHelper like:
public static PartialModel GetPartialModel(this HtmlHelper helper)
{
return helper.viewContext.ViewData["PartialModel"] as PartialModel
}
So you could obtaint the model this way:
<% Html.RenderPartial("MyPartial", Html.GetPartialModel()); %>

ASP.NET MVC how to bind custom model to view

I would like bind an array data to view in ASP.NET MVC, how can I do that?
sorry for not clear about my question.
Right now, I creat a custom object(not array), I tried to pass it to View, but the error shows
"The model item passed into the dictionary is of type 'ContactView' but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable"
You can use the ViewData[], but the best way would be to actually create a view class and return that.
So let's say the view you want to send the data is called Contacts. Create a new View class and return that. so instead of this:
public ActionResult Contacts(){
ViewData["contacts"] = arrayOfContacts[];
...
return View();
}
You can get strongly-typed views by doing this:
public class ContactsView(){
Object[] ContactsList {get;set;}
}
public ActionResult Contacts(){
...
return View(new ContactsView(){
ContactsList = arrayOfContacts[];
});
}
Then in the actual view, you can have it be strongly typed by accepting objects of type ContactsView. That way in the actual View, have it inherit like so:
... Inherits="System.Web.Mvc.ViewPage<ContactsView>" ...
Which allows you to call your array like...
Model.ContactsList
as opposed to this:
object[] arrayOfItems = (Object[])ViewData["theContactsList"];
In which case you'd probably want to check if it's not null, etc. The benefit of this is that if you refactor it's much easier. Not to mention the ease and type security of use of strongly typed objects.
Put it in the ViewData, and use for..each to loop through it?
Look at this link: http://nerddinnerbook.s3.amazonaws.com/Part6.htm
Basically you could load the array into a viewdata object, and use that as you like.

Resources