I`m writing an ASP.Net MVC application with Razor.
Assume that I have HomeController and some views for it.
1. View1
2. View2
3. View3
All this views use common _MyLayout file, which should look like this:
When the links are clicked, the views are rendered by RenderBody() method.
Each view is strongly typed: it requires its own Model.
Everything was fine untill I decided to add special Model to _MyLayout view.
But now I get error
The model item passed into the dictionary is of type 'TestUp.Models.UserModels.PendingTestsModel', but this dictionary requires a model item of type 'TestUp.Models.UserModels.UserNavigationModel'.
Here is controllers code
public ActionResult View1()
{
ModelForView1 model = new ModelForView1();
return View(model);
}
public ActionResult View2()
{
ModelForView2 model = new ModelForView2();
return View(model);
}
public ActionResult View3()
{
ModelForView3 model = new ModelForView3();
return View(model);
}
Shortly speaking if layout view doesn`t require model, specific method for View is invoked,
model is created, passed to view and everything is ok. But now layout requires model as well so it crashes.
The question is: how do I elegantly resolve this problem?
Desired workflow is:
View1 is requested
Method in controller for this view is called, model instance created, passed to view
Some method for layout is called, model for layout created, passed to layout.
Is it possible to make things work somehow like this?
Thanks.
Create a base model type and have your specific view models extend it. This base model can have a property of type UserNavigationModel. The layout can accept the base model and use the new property as the model for the navigation menu.
public abstract class ModelBase
{
public UserNavigationModel NavigationModel { get; set; }
}
public class ModelForView1 : ModelBase { ... }
public class ModelForView2 : ModelBase { ... }
public class ModelForView3 : ModelBase { ... }
View1:
#model ModelForView1
Layout:
#model ModelBase
#* use Model.NavigationModel for nav bar *#
Related
I have a Web app where my controller passes a model to the parent view like so:
public ActionResult Results()
{
//Processing
return View ("ParentView",model);
}
Within my "ParentView" I will do render a partial view like so:
#Html.Partial("_PartialView", anotherModel)
Now I would like to not touch the anotherModel at all.
But what I am trying to do is pass a value to _PartialView from the ParentView.
I know I can pass something like ViewBag.Value="Text" from the Controller to the "ParentView", however is something like that doable from "ParentView" to "_PartialView"?
Basically I want to add a value in the model that is being used by "ParentView", and somehow pass it down to "_PartialView"
You will have to create a View model. you can create it by 3 ways
first way
public class ViewModel
{
public class ParentViewModel {get; set;}
public class ChildViewModel {get; set;}
}
in this case your view
#model ViewModel
...... //html is using #Model.ParentViewModel)
#Html.Partial("_PartialView", #Model.ChildViewModel)
second way
public class ParentViewModel:ChildViewModel
in this case the same model can be used for both
#model ParentViewModel
...... //html is using #Model)
#Html.Partial("_PartialView")
The third way can be used if it is possible to use interface to another model
partial view
#model IAnotherModel
viewmodel
public class ViewModel:IAnotherModel
view is the same as the second way
You can pass properties from your PageView Model to your PartialView like this:
#Html.Partial("_PartialView", #Model.AnotherModel)
You then set the Model of your _PartialView to be of the type of AnotherModel.
I am Newer in ASP.NET MVC. I can not Clearly Understand the difference among
Strongly Typed view vs Normal View vs Partial View vs Dynamic-type View
in Asp.NET MVC. Anyone describe me about this terms.
Thanks in advance!!!
Strongly Typed view
A view which is bound to a view model. For example if you have the following view model:
public class MyViewModel
{
public string SomeProperty { get; set; }
}
that is passed to the view by the controller action:
public ActionResult Index()
{
var model = new MyViewModel();
model.SomeProperty = "some property value";
return View(model);
}
the strongly typed view will have the #model directive at the top pointing to this view model:
#model MyViewModel
...
<div>#Model.SomeProperty</div>
Partial View
The difference between a view and a partial view is that a partial view only contains some small HTML fragments that can be reused in multiple parts of a normal view. For example you could define the following partial view:
#model AddressViewModel
<div>Street: #Model.Street</div>
<div>Country: #Model.Country</div>
and then render this partial view at multiple places in your main view to avoid repetition of the same code over and over:
#model MainViewModel
...
<h3>Personal address</h3>
<div>#Html.Partial("_Address.cshtml", Model.PersonalAddress)</div>
...
<h3>Business address</h3>
<div>#Html.Partial("_Address.cshtml", Model.BusinessAddress)</div>
Dynamic-type View
A view which doesn't have a model or one that uses weakly typed structures such as ViewBag. For example you could have a controller action which sets some property in the ViewBag:
public ActionResult Index()
{
ViewBag["SomeProperty"] = "some property value";
return View();
}
and the corresponding view you could access this property by using the same key in the ViewBag:
<div>#ViewBag["SomeProperty"]</div>
I am a beginner in ASP.NET MVC.
My page has one partial view called _Navigation that I am reusing.
If the user is in the "Home" the <a> of the navigation needs to point to the "#" char, if the user is in the "Services" page, the href of the navigation needs to point to other url, let's say "www.mysite.com". It will occur with other links in this menu too.
I tried to do the following
#if (ViewContext.RouteData.Values.ContainsValue("Services"))
{
#model MySite.Models.ServicesNavigation
}
else
{
#model MySite.Models.HomeNavigation
}
But it says I can have only one model.
How to solve it?
You can try using Interface.
public interface INavigation
{
//Your props here
}
public class ServicesNavigation : INavigation
{
}
public class HomeNavigation: INavigation
{
}
Then your view can be of type INavigation.
#model INavigation
And in your controller based on your conditions you can pass the impementation of INavigation you want.
.......
INavigation model;
if(conditionOneIsMet)
{
model = new ServicesNavigation();
}
else
{
model = new HomeNavigation();
}
return View(model);
Your view is in fact a class derived from the WebViewPage<TModel> class. The #model statement defines type of the model (TModel) Because it is the compile time statement, you can't change it in run time.
If you need two different models, you should have two different views.
This is the view:
#model tgpwebged.Models.sistema_DocType
...
this model is an entity used with textBoxFor and others html helpers
This is the controller.
public ActionResult AdminSettingAddTipo()
{
IEnumerable<string> indices;
using (tgpwebgedEntities context = new tgpwebgedEntities())
{
var obj = from u in context.sistema_Indexes select u.idName;
indices = obj.ToList();
}
return PartialView(indices);
}
I have all I need here, I am using a model to create with the view so I am not allowed to send ´indices´ as a model because it´s not allowed to have 2 models in one view.
I don´t want to use ´Tupe´ now a parent view. I just want to know how is the best way to send my IEnumerable to the view.
I was thinking of ViewBag for the last option but I am avoiding ViewBag.
thanks
ViewBag is not a good choice. Create ViewModel using your list and your current Model:
public class YourViewModel
{
public sistema_DocType Type { get; set; }
public IEnumerable<string> Indices {get;set;}
}
Hope,it will help.
If you don't want to use ViewBag for whatever reason, you could create a Model specifically for the view that contains the info from the old model and the new indices you want. This is a common pattern in MVC development. You can even have the ViewModel be a Decorator for your current Model.
http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx
Use strongly defined where you can, apply this to a model and send that model:
Model
public class MyModel{
public List<sistema_Indexes> indecies {get;set;}
}
Controller
MyModel model = new MyModel();
model.indecies = context.sistema_Indexes.Select(u=> u.idName).ToList();
I have a view model as such:
public class MyViewModel
{
public MyObject myObject{ get; set; }
public List<MyList> myList{ get; set; }
}
I have a view with a form strongly typed to MyViewModel
This view allows you to enter values for the properties of MyObject, as well as create a list of MyList objects. The List part works fine although I thought that would be the more difficult of the two.
Assuming MyObject has a property Description I create a textbox to enter the value as such:
#Html.EditorFor(x => x.myObject.Description);
The text box renders with an id of MyObject_Description...The problem is when I post this to my controller action, MyObject does not get bound at all(althought the list items do as they recieve the appropriate IDs of "MyViewModel_MyList[guid].myListValue")
What am I doing wrong here??
EDIT: more info
The first line of the view is:
#model MyApp.ViewModels.MyViewModel
And the Action method:
[HttpPost]
public ActionResult Create(MyViewModel myViewModel)
{
}
I am passing a new MyViewModel into the partial view to begin...
public ActionResult Create()
{
MyViewModel model = new MyViewModel();
return PartialView(model);
}
EDIT 2
Ok When I render my partial view that contains the forms I call :
#{Html.RenderAction("Create", "MyController");}
this is called from within a View of type #model IEnumerable<MyApp.Models.MyObject>
(this view displays a list of currently existing MyOjects, and at the bottom the partial is rendered to allow the user to add another MyObject to the DB)
If you are not already doing so, try creating a editor template (e.g., Views->Shared->EditorTemplates) called MyObject.cshtml. Move your partial view content to this view and then call
#Html.Editor("myObject").
from your parent partial view.
Change your ViewModel to have the Description directly
public class MyViewModel
{
public string Description { get; set; }
public List<MyList> myList{ get; set; }
}
then bind accordingly
#Html.EditorFor(x => x.Description);
I would expect the top line of your view to look something like this:
<%# Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<MyViewModel>" %>
This tells the view that the model it is supplied is of type MyViewModel (a la <T> style).
I don't think the out of the box model binding knows how to bind to complex objects. You're probably going to have to write up some sort of custom model binder.
I'm afraid it's not something I've done since MVC1 so I'm a bit hesitant to give you any sample code because the mechanism may well have changed completely since then. A quick google did turn up this article http://www.learnxpress.com/asp-net-mvc-hosting-6-tips-for-asp-net-mvc-model-binding-2.html and this article http://bradwilson.typepad.com/blog/2010/10/service-location-pt9-model-binders.html.
Edit: I've just seen this answer which might help Retrieving data from view, should I use model binder?