I feel stupid asking this but I cant seem to get a partial view rendering in a page.
I have created a partial view that im trying to load into my index page. I have called my pv _BusinessDetails basically its a view that returns some customer data.
My pv looks like
#model MyMVC.Models.BusinessModel
<div class="grid">
<div class="grid-header">
<div class="gh-l"></div>
<div class="gh-m">Business Details</div>
<div class="gh-r"></div>
</div>
<div class="grid-row">
<label class="labelBold">Busines Name</label>
<label>#Model.BusinesName</label>
</div>
</div>
From my index page I am trying to call the pv using
#Html.Partial("_BusinessDetails")
which fails so if I add
#Html.Partial("_BusinessDetails",new MyMVC.Models.BusinessModel())
The partial view is loaded however with no data as the controller isn't been hit. In my controller I have tried
public ActionResult _BusinessDetails()
{
return PartialView("_BusinessDetails");
}
public PartialViewResult _BusinessDetails()
{
return PartialView("_BusinessDetails");
}
However neither of them are hit. What have I done wrong?
When rendering a partial view and passing a view model, that view model should already be populated. No controllers/action methods are invoked when using #Html.Partial().
Since you are using this strongly-typed partial view on your home page, consider building its view model in your HomeController's Index() method. Is your index page strongly-typed as well? If so, you can add your partial view's view model as a property of your index page's view model, and pass that when calling #Html.Partial().
On your index page, it would look something like:
#model MyMVC.Models.IndexViewModel
<!-- some HTML here -->
#Html.RenderPartial("_BusinessDetails", Model.BusinessModel)
If your index page is not strongly-typed, you can use the ViewBag object or you can strongly-type it to MyMVC.Models.BusinessModel and use #Html.RenderPartial("_BusinessDetails", Model) (which, while simple, could cause confusion).
Rachel Appel has a nice blog post, as does Mike Brind, if you would like more information.
It's tricky. I've had success with using a model on the main view as a container object:
class MainPageModel {
public BusinessDetailModel BusinessDetails { get; set; }
// ...
}
and then just passing the whole model like #Html.Partial("_BusinessDetails", Model) to my partial views.
When you wrote this,
#Html.Partial("_BusinessDetails",new MyMVC.Models.BusinessModel())
The data is not loaded as your model is empty, so before passing model BusinessModel,fill it before.
Related
I have a main Index view from which I call view called Create, into which I pass type of the widget I want to create as a string.
Index view:
<i class="fa fa-image"></i> Create Image Widget -
<i class="fa fa-file-text"></i> Create Text Widget
Create Action:
public ActionResult Create(string wType)
{
ViewBag.wType = wType;
return View();
}
the type is then passed into view via ViewBag.wType and this is evaluated in the Create View
Create view:
#using (Html.BeginForm())
{
<section class="row">
#{
if (ViewBag.wType == "image")
{
Html.RenderPartial("~/Views/WidgetEditor/_CreateImageWidget.cshtml");
}
else if (ViewBag.wType == "text")
{
Html.RenderPartial("~/Views/WidgetEditor/_CreateTextWidget.cshtml");
}
}
</section>
}
and depending on this, appropriate partial view is loaded.
Partial views have different models so when the form is submitted, I do not know how which model is passed back. The one from _CreateImageWidget or _CreateTextWidget.
If the HttpPost controller look like this
[HttpPost]
public ActionResult Create(DisplayWidgetImageViewModel imageModel, DisplayWidgetTextViewModel textModel)
{
return new ViewResult();
}
I will get populated imageModel if _CreateImageWidget partial is chosen and textMode if _CreateTextWidget partial is chosen.
This is acceptable it the number of widgets types does not change, but this is not the case.
Is there a way to get somehow specific model from a partial view and know/find out which one it is or am I doing this completely wrong way?
You can create multiple forms in single page. You can also use different action methods per partial:
#using (Html.BeginForm("Action", "Controller")) {
Html.RenderPartial("~/Views/WidgetEditor/_CreateImageWidget.cshtml")
}
You all this without having to use Ajax.
I have used this answer to solve my problem: determine-the-model-of-a-partial-view-from-the-controller-within-mvc
there are also several other link with more resources.
My MVC page has a Parent view that show the Parish page. Every Parish has multiple Churches and Every Church has its Own mass times. Parish page has Churches as Partial View but I want to use Church ID to render another Parital view of Mass times (Stored Procidure). How can use the ID of a partial view and create anothe partial view. I had been banging my head but unable to get this resolved.
render the Partial view in Side the Div tag. Then use the div ID and Clone the div to create a another partial view.
See below code sample.
<Div id="SomeId">
//Render your partial view here.
</Div>
Clone the Div and create as many partial view u need.
I finally got it working... I was now able to get the Partial view work...
Stored Procedure inside the controller:
public ActionResult Timing(int id)
{
var massTimings = db.masTimings(id);
return PartialView(massTimings);
}
My View inside Locations Partial View:
#Html.Action("Timing",new {id = item.LocationID})
I am wondering about a couple variations of forms and partial forms. The submit is on the parent page and I have varied what I pass to the partial view. I have a parent view with a related HomeViewModel (which has public properties Name and public Person Employee {get;set;}
1.) Scenario 1: The main view has something like the following
#model MasterDetailSample.Models.HomeViewModel
#using (Html.BeginForm()) {
<div>
#{Html.RenderPartial("_PersonView", #Model);}
</div>
<input type="submit" value="Save" />
}
In this scenario I am passing to the partial view _PersonView the entire HomeViewModel. Within _PersonView partial view I have to reference a property of the HomeViewModel i.e. Person object via #model.Employee.Name (in this scenario the submit is on the parent form (not within the partial view))
When I hit submit on the form (POST) in the controller i have to access the property of Employee "Name" via the following model.Employee.Name
This seems to work however notice the following variation scenario 2 (where I only pass to the partial the Employee object)
2.) Scenario 2
In this scenario I only want to send the Employee object to the partial view. Again the begin form and submit is on the parent form.
So from the parent form i have
#{Html.RenderPartial("_MasterView", #Model.Employee);}
and so within the partial view i reference the Name property of the Person object via #Employee.Name Now when I submit the form within the controller the Employee object is not available from the auto model binder. I can access the properties via formcollection but not from the model parameter
i.e.
[HttpPost]
public ActionResult Index(ModelViewModel model) {
**//model.Employee is null!**
return View();
}
Why? (is model.Employee null) I would like my partial view to only accept an object of type Person however after submitting from the parent page, the Employee property is null. On the partial view I am using the following on the #model line
#model MasterDetailSample.Models.Person
I would like the partial to only need a Person object to be sent to it, but I would like the submit on the main form. If i do it this way I can re-use the partial view in a few situations however IF i must send HomeViewModel i have significantly limited how I can use this partial view. So, again, I only want to use Person as the model with the partial view but I need to be able to access the properties when submitted from the parent view.
Can this be done? If yes how?
thx
You have a couple of options:
1) One I recommend -> Dont use partial views, instead use EditorFor and create an editor template for Person. With partial views the context is whatever model you pass into the view, this is why your example (1) works and (2) not. However with editor templates the parent context is taken into consideration with the html helpers and will generate the correct input names. Have a look at Darin Dimitrov's answer to a similar question.
2) Use your second example as is, but change the post action to look something like this:
[HttpPost]
public ActionResult Index(ModelViewModel model) {
TryUpdateModel(model.Employee);
**//model.Employee should now be filled!**
return View();
}
3) Use custom html helpers that accepts prefix for input, see this answer I posted a while back for example code. You could then use this inside your partial view.
I have a strongly typed razor view for a model in my MVC 3 project. Basically its for editing the model.
The model contains an Id field for the database key and some other string fields (Its a viewModel and all but thats not the point of the question).
In the view I just have a form and a submit button and nothing else. When the View is posted to the controller the model in the controller has all fields empty EXCEPT for the Id field which seems to have been auto-magically filled up.
How and where does the Id field gets populated in the model without there being a corresponding 'input' element for it in the view.
This is probably a dumb question but I would appreciate even just a link to what I should read up on. Thanks.
I bet it comes from the url as route parameter.
For example you have the following controller:
public class HomeController: Controller
{
public ActionResult Index(int id)
{
vqr model = GetModel(id);
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// the model.Id property will be automatically populated here
// because the request was POST /home/index/123
...
}
}
and the following view:
#model MyViewModel
#using (Html.BeginForm())
{
<button type="submit">OK</button>
}
Now you navigate to GET /home/index/123 and you get the following markup:
<form action="/home/index/123" method="post">
<button type="submit">OK</button>
</form>
Notice the action attribute of the form? That's where the id comes from. Basically the Html.BeginForm() helper uses the current url when generating the action attribute, and since the current url is /home/index/123 it is what gets used.
And because if you have left the default routes in your Global.asax, the {id} route token is used at the end of the url, the default model binder successfully binds it to the Id property of your view model.
You are probably hitting a URL similar to the following: /MyObject/Edit/15
This is then returning the page that you have your blank form on.
What happens next is you have an HTML.BeginForm() which is posting BACK to /MyObject/Edit/15
Now because of the post back having the same format your routing rules are picking up the '15' and binding it back to your id.
Have you added the ID field as a hidden field?
e.g.
#Html.HiddenFor(x=> x.ID)
Im creating an application that allows me to record recipes. Im trying to create a view that allows me to add the basics of a recipe e.g. recipe name,date of recipe, temp cooked at & ingredients used.
I am creating a view that contains some jquery to load a partial view clientside.
On post im having a few troubles trying to get the values from the partial view that has been loaded using jquery.
A cut down version of my main view looks like (I initially want 1 partial view loaded)
<div id="ingredients">
#{ Html.RenderPartial("_AddIngredient", new IngredientViewModel()); }
</div>
<script type="text/javascript">
$(document).ready(function () {
var dest = $("#ingredients");
$("#add-ingredient").click(function () {
loadPartial();
});
function loadPartial() {
$.get("/Recipe/AddIngredient", {}, function (data) { $('#ingredients').append(data); }, "html");
};
});
</script>
My partial view looks like
<div class="ingredient-name">
#Html.LabelFor(x => Model.IngredientModel.IngredientName)
#Html.TextBoxFor(x => Model.IngredientModel.IngredientName)
</div>
<div class="ingredient-measurementamount">
#Html.LabelFor(x => Model.MeasurementAmount)
#Html.TextBoxFor(x => Model.MeasurementAmount)
</div>
<div class="ingredient-measurementtype">
#Html.LabelFor(x => Model.MeasurementType)
#Html.TextBoxFor(x => Model.MeasurementType)
</div>
Controller Post
[HttpPost]
public ActionResult Create(RecipeViewModel vm,IEnumerable<string>IngredientName, IEnumerable<string> MeasurementAmount, IEnumerable<string> MeasurementType)
{
Finally my viewmodel looks like
public class IngredientViewModel
{
public RecipeModel RecipeModel { get; set; }
public IEnumerable<IngredientModel> Ingredients { get; set; }
}
My controller is pretty ugly......im using Inumerble to get the values for MeasurementAmount & MeasurementType (IngredientName always returns null), Ideally I thought on the httppost Ingredients would be populated with all of the on I would be able Ingredients populated
What do I need to do to get the values from my partial view into my controller?
Why don't you take a look at the MVC Controlstoolkit
I think they would do what you want.
Without getting in too much detail. Can you change the public ActionResult Create to use FormCollection instead of a view model? This will allow you to see what data is coming through if any. It would help if you could post it then.
Your view model gets populated by using Binding - if you haven't read about it, it might be a good idea to do that. Finally I would consider wrapping your lists or enums into a single view model.
Possible Problem
The problem could lay with the fact that the new Partial you just rendered isn't correctly binded with your ViewModel that you post later on.
If you inspect the elements with firebug then the elements in the Partial should be named/Id'ed something like this: Ingredients[x].Property1,Ingredients[x].Property2 etc.
In your situation when you add a partial they are probably just called Property1,Property2.
Possible Solution
Give your properties in your partial the correct name that corresponds with your List of Ingredients. Something like this:
#Html.TextBox("Ingredients[x].Property1","")
Of, after rendering your partial just change all the names en ID's with jquery to the correct value.
It happens because fields' names from partial view do not fit in default ModelBinder convention. You should analyze what names fields have in your partial view.
Also you should implement correct way of binding collections to MVC controller. You could find example in Phil's Haack post
Assuming RecipeViewModel is the model being supplied to the partial view, try just accepting that back in your POST controller like this:
[HttpPost]
public ActionResult Create(RecipeViewModel vm)
{
//
}
You should get the model populated with all the values supplied in the form.