Regarding loading of partial view in mvc - asp.net-mvc-3

i am new in mvc. now learning. i was searching various technique to load partial view in mvc and i got good one in stackoverflow. here it is.
If you want to load the partial view directly inside the main view you could use the Html.Action helper:
#Html.Action("Load", "Home")
or if you don't want to go through the Load action use the HtmlPartial hepler:
#Html.Partial("_LoadView")
If you want to use Ajax.ActionLink, replace your Html.ActionLink with:
#Ajax.ActionLink(
"load partial view",
"Load",
"Home",
new AjaxOptions { UpdateTargetId = "result" }
)
and of course you need to include a holder in your page where the partial will be displayed:
<div id="result"></div>
Also don't forget to include:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
in your main view in order to enable Ajax.* helpers. And make sure that unobtrusive javascript is enabled in your web.config (it should be by default):
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
after going through the above code one confusion occur. help require. my confusion as below.
#Html.Action("Load", "Home")
#Html.Partial("_LoadView")
i know the use of #Html.Partial("_LoadView") but do not understand how #Html.Action("Load", "Home") will work ?
can anyone show me couple of example to show the various usage of
#Html.Action("Load", "Home")
and how it is different from #Html.Partial("_LoadView")
thanks

Html.Partial
Renders the partial view as an HTML-encoded string.
This method result can be stored in a variable, since it returns string type value.
Simple to use and no need to create any action.
Partial method is useful used when the displaying data in the partial view is already in the corresponding view model.For example : In a blog to show comments of an article, we would like to use RenderPartial method since an article information with comments are already populated in the view model.
#Html.Partial("_Comments")
Html.Action
Renders the partial view as an HtmlString .
For this method, we need to create a child action for the rendering the partial view.
This method result can be stored in a variable, since it returns string type value.
Action method is useful when the displaying data in the partial view is independent from corresponding view model.For example : In a blog to show category list on each and every page, we would like to use Action method since the list of category is populated by the different model.
#{Html.Action("Category","Home");}

#Html.Action("Load", "Home")
Will execute the "Load" ActionResult in your "HomeController".
This Action may return any of these (ref: MSDN):
ContentResult
EmptyResult
FileResult
HttpUnauthorizedResult
JavaScriptResult
JsonResult
RedirectResult
RedirectToRouteResult
ViewResultBase
While
#Html.Partial("_LoadView")
Will insert your partial view "_LoadView" into your current view.
If you're familiar with web forms, think of your partial views as .ascx (user controls).
Edit:
Example of usage of #Html.Action():
Say you have this view:
<p>Here is my name: #Html.Action("Name")</p>
And this is my controller (As you see, I use the overload of Html.Action() that implicit uses the controller you're routed to):
public class FooController : Controller
{
//
// GET: /Foo/
public ActionResult Index()
{
return View();
}
// GET: /Foo/Name
public ActionResult Name()
{
return Content("Annish");
}
}

Related

Constructing HTML in Controller - how to refactor?

I'm currently generating breadcrumbs on an object's Details page by calling a GetBreadcrumbs() method in the object's controller - in this method, the object's parent/grandparent are used to generate an unordered list. What's the best way to pull the HTML out of the controller to follow the Separation of Concerns paradigm? Should a partial view be used here?
Typical example of partial view is Breadcrum itself. For example, in your controller you can have
//
//GET: News/Article/x
public ActionResult Article(int id)
{
//get parentid of article
ViewBag.id = id;
ViewBag.parentid;
return View();
}
So, your partial view will be as below:
#{
ViewBag.Title = "Article";
}
<h2>Viewing Article #ViewBag.parentid >> #ViewBag.id</h2>
You could use partial views or display templates. Your controller should only build the model that will be passed to the view and then inside the view you could use a display template that will build the desired output based on the model.

How can we include a form in _layout?

I currently have a _layout.cshtml used by every page of my website.
I need to put a form on each page displayed as a popin.
So, i created a new PartialView (the content of my form) with its corresponding ViewModel and called it in _layout.cshtml.
However, i have a model conflict between ViewModels of pages using the layout and the ViewModel used by the new form (since we can't have directly two models for the same view).
The model item passed into the dictionary is of type 'XXX', but this
dictionary requires a model item of type 'YYY'.
How can we include a form in _layout without this conflict ?
The following has worked for me with a sidebar on every page.
Create a controller for your partial view
In that controller, create a method for the view you want to return, and be sure to use the [ChildActionOnly] filter
public class PartialController : Controller
{
[ChildActionOnly]
public PartialViewResult Alerts()
{
return PartialView("Alerts", messages);
}
}
In your _layout view, you'll have the following:
#Html.Action("Alerts", "Partial")
(instead of #Html.RenderPartial or #Html.Partial)
It sounds like you already have what you need for the view.
I have not used this with a form, but it should work similarly. Hope this helps.

MVC 3 Partial View and what I need to send to it?

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.

My controller viewmodel isn't been populated with my dynamic views model

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.

Modifying MVC 3 ViewBag in a partial view does not persist to the _Layout.cshtml

I am using MVC 3 with the Razor view engine. I want to set some values in the ViewBag inside a Partial View and want retrieve those values in my _Layout.cshtml. For example, when you setup a default ASP.NET MVC 3 project you get a _Layout.cshtml file in the "/Views/Shared" folder. In that _Layout.cshtml the Page Title is set like this:
<title>#ViewBag.PageTitle</title>
Then in "/Views/Home/About.cshtml" view the contents of the ViewBag are modified:
#{
ViewBag.Title = "About Us";
}
This works fine. When the About view is rendered the page title is "About Us". So, now I want to render a Partial view inside my About view and I want to modify the ViewBag.Title inside my Partial view. ("/Views/Shared/SomePartial.cshtml")
#Html.Partial("SomePartial")
In this Partial view I have this code:
#{
ViewBag.Title = "About Us From The Partial View";
}
When I debug this code I see the ViewBag.Title get set to "About Us" and then in the Partial view I see it get reset to "About Us From The Partial View", but when the code hits the _Layout.cshtml it goes back to "About Us".
Does this mean that if the contents of the ViewBag are modified in a Partial view, those changes will not appear(be accessible) in the main view (About.cshtml) or the _Layout.cshtml?
Thanks in advance!
If you pass the ViewBag into the partial's viewdatadictionary, then pull it out (and cast), you can do whatever you want and the reference is kept. The cool part is that since it's dynamic, you can even add properties and then they'll show up on the parent page's Viewbag.
Page:
//set the viewbag into the partial's view data
#{Html.RenderPartial("Elaborate", Model, new ViewDataDictionary { {"vb", ViewBag}});}
Partial:
#{
var vb = ((dynamic)ViewData["vb"]);
vb.TheTitle = "New values";
}
Page
#ViewBag.TheTitle = "New value"
I also had this problem, and couldn't find any neat and obvious solution.
The solution I came up with was to implement an Html extension method that returns a 'PageData' class that you define, containing whatever data you need:
[ThreadStatic]
private static ControllerBase pageDataController;
[ThreadStatic]
private static PageData pageData;
public static PageData GetPageData(this HtmlHelper html) {
ControllerBase controller = html.ViewContext.Controller;
while (controller.ControllerContext.IsChildAction) {
controller = controller.ControllerContext.ParentActionViewContext.Controller;
}
if (pageDataController == controller) {
return pageData;
} else {
pageDataController = controller;
pageData = new PageData();
return pageData;
}
}
It finds the top-level controller for the current request, and returns the same PageData object every time the method is called within the same HTTP request. It creates a new PageData object the first time it is called in a new HTTP request.
The partial view gets its own ViewBag.
You can get the page's ViewBag from ((WebViewPage) WebPageContext.Current.Page).ViewBag
You can do this trick in your partial view to override the title in your _Layout.cshtml:
#{
ViewBag.Title = "About Us From The Partial View";
}
......
<script type="text/javascript">
document.title = "#ViewBag.Title";
</script>
As others have pointed out Layout, Views and Partials get their own ViewBag. However, I was able to get it to work with the following:
In the View or Partial.
#{ Html.ViewContext.ViewBag.Title = "Reusable Global Variable"; }
Then in _Layout
#Html.ViewContext.ViewBag.Title
By explicitly using the ViewContext, the views 're-use' the same ViewBag.
If anyone is still looking for a solution to this it appears that you can do it with TempData:
TempData["x"] = x;
TempData is persisted until it is read so you can just read it in your _Layout. You just have to be careful that you read everything so that it is cleared for the next request.
I've tried the following and it works:
In the (parent) view...
#Html.Partial("SomePartial", ViewData, null)
Note: ViewData is passed as the model argument, but you have to specify null for the viewData argument to use the correct overload. You can't use ViewBag because Html.Partial doesn't like dynamics.
Then , in the partial view...
#model ViewDataDictionary
#{
Model["Title"] = "About us from the partial view";
}
Of course, if you need to use the model argument for a real model, you'll have to be more creative.
try #SLaks code with
(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
I encountered the same problem when I use mvc3, and I found that
this.ViewBag.ViewBag.PropertyName
works in your custom control.
I this is what page data is designed for. Pop this into your view.
#Page.somePropertyName = "Whatever you want";
And then access it in your layout view. Be sure to check that its not null first.
#{
if(Page.somePropertyName != null)
{
//Do stuff
}
}

Resources