RenderPartial Problem (While sending data to master page) - asp.net-mvc

I am trying to send some data the master page. I am using Razor as my View Engine, and AutoMapper to map between Domain and View Models. Below is my code:
//the partial view action method:
public ActionResult RenderCategories()
{
IEnumerable<TopLevelCategory> categories = _categoryService.GetTopLevelCategories();
var viewModel = new MasterPageViewModel
{
Categories =
Mapper.Map
<IEnumerable<TopLevelCategory>, IEnumerable<ParentCategory>>(categories)
};
return View(viewModel);
}
//the partial view file: (this is just a test for now)
#model Sharwe.MVC.ViewModels.MasterPageViewModel
#foreach (var item in Model.Categories) {
#item.Name
}
public class MasterPageViewModel
{
public IEnumerable<ParentCategory> Categories { get; set; }
}
I'm calling the partial view using #Html.RenderPartial("RenderCategories") from inside my _Layout.cshtml file. But I keep getting the following error:
Compiler Error Message: CS1502: The
best overloaded method match for
'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)'
has some invalid arguments
What's going on?

The RenderPartial extension method writes directly to the output stream and has no return type (void). So here's the correct syntax to call it:
#{Html.RenderPartial("RenderCategories");}
or if you prefer you could use the Partial extension method:
#Html.Partial("RenderCategories")
Contrast those with their equivalents in the WebForms view engine:
<% Html.RenderPartial("RenderCategories"); %>
<%= Html.Partial("RenderCategories") %>

Related

MVC5 HTML ActionLink Throws CS1502

I've created a very simple view class in my MVC5 solution. It uses the Entity Framework and calls one of the controller class's actions. I want to output a list of VIN numbers as hyperlinks on my home page.
The view class syntax is as follows:
#{
ViewBag.Title = "Vehicle Inventory";
}
#model IEnumerable<TavernaMVC.Controllers.InventoryController>
<ul>
#foreach (var item in Model)
{
<li>#item</li>
}
</ul>
The error is as follows:
CS1502: The best overloaded method match for
'System.Tuple.Create<object,int>(object, int)' has some invalid arguments
How do I rectify my code so that each VIN's details are output in the view class? Alternatively, how would I simply output all the VIN values as hyperlinks?
First, you should not use your controller as model. What model class are you using? Since you're talking about VIN I will guess it can be called Car:
public class Car {
public int VIN { get; set; }
public string Details { get; set; }
}
In your controller you would then like to do something like:
public ActionResult Index() {
var cars = db.Cars.ToList();
return View(cars);
}
Then, define your view as:
#model IEnumerable<TavernaMVC.Models.Car>
#{
ViewBag.Title = "Vehicle Inventory";
}
<ul>
#foreach (var item in Model)
{
<li>#item.VIN</li>
}
</ul>
Your view looks correct if the TavernaMVC.Controllers.InventoryController class looks somewhat like:
public class TavernaMVC.Controllers.InventoryController
{
//VIN
public string VIN{get;set;}
//Url to Details
public URL Details{get;set;}
}
and you use this
<li>#item.VIN</li>
as the li line
Check for renamed Properties in the first line ...
I had this error after renaming a Property and using the AutoRefactoring in the Visual Studio which does not change the Properties in CSHTM files.

Passing Data From View back to the HttpPost method in MVC

Alright so i want to pass data from the view back to Post Method in the controller.
The View :
#model IEnumerable< MvcMobile.Models.Trips>
<p>Time : #ViewBag.titi</p>
<p>ID :#ViewBag.iid </p>
<p>From : #ViewBag.From</p>
<p>To :#ViewBag.To </p>
Avaibliabe Trips :
#foreach (var item in Model)
{
if ( item.Time==ViewBag.titi)
{
<p>#item.TripID</p>
}
}
My HttpGet Method in the controller :
[HttpGet]
public ActionResult Book2(MvcMobile.Models.TicketsBooked tik)
{
ViewBag.titi = tik.Time;
ViewBag.iid = tik.TicketID;
ViewBag.from = tik.From;
ViewBag.To = tik.To;
var TripsList = db.Trips.ToList();
return View(TripsList);
}
In This case i cant use a dynamic object to pass variable since the model is IEnumerable
i want to pass one or two textBoxes back to the controller, how can i do that ?
an alternative question would be how can i do the same functionality in the view without making the model IEnumberable ?
and thanks alot.
You should read up on using view models. Basically it's best practice to only pass relevant data to the view. So instead on passing a model of IEnumerable you would have a view model with a property of IEnumerable plus the extra properties you want to post back to your controller.
So for example:
public class ViewModel
{
public IEnumerable<MvcMobile.Models.Trips> Trips { get; set; }
public string ExtraValue { get; set; }
}
and your view would be:
#foreach(var trip in Model.Trips)
{
<p>Do stuff</p>
}
#Html.TextBoxFor(m => m.ExtraValue)
Your post method would then accept a ViewModel.
[HttpPost]
public ActionResult Book2(ViewModel viewModel)
{
}
You can read up more on view models here or by searching Google / SO. There are many, many examples.

pass viewModel object from controller to view in asp.net MVC

I have the following method in controller
public ActionResult Categorized()
{
var x=new Test.Models.MobileClass();
return View(x);
}
x object contains methods that return xmldocument data
how can I pass this object to view to access methods and display data from xmldocument in browser
I can display it element element by using the following code
document.writeln("#Model.getxml().ChildNodes.Count");
but I want to use for loop displaying the contents of object and the following code didn't work in javascript
var size=parseInt("#Model.Getxml().ChildNodes.Count");
for (var i=0; i<size; i++)
{
document.writeln("#Model.Getxml().ChildNodes[i].InnerText");
}
can you help me please
First of all, your view should not be calling Getxml and mucking about with the XML DOM. It's the job of the controller to present the view with "ready to render" data. That's what a ViewModel is for.
public ActionResult Categorized()
{
var foo = new Test.Models.MobileClass();
var xml = foo.Getxml();
var viewData = xml.ChildNodes.Cast<XmlNode>().Select(x => x.InnerText);
return View(viewData);
}
Now we're passing an IEnumerable<string> to the view, containing just the values we want to render.
In the view, you should not be using javascript to render your data to HTML - use the view to render your data to HTML - the Razor template engine is really good at that! Something like...
<ul>
#foreach (var item in Model) {
<li>#item</li>
}
</ul>
The javascript will fail, since the variable i will be evaluated on the server side and doesn't exist then.
Use a foreach in the view, with razor:
#foreach(var child in Model.Getxml().ChildNodes)
{
child.InnerText
}

How to populate mvc razor partial view

I need to create a view that displays Order Header information and I need to add a patial view that displays a grid of Line Items. The partial view will be strongly typed from a viewmodel. I understand that I should use the html helper #Html.Partial("Path/view"). I have only used controllers up til now to open a view, populating the viewmodel before sending it to the view. Since the partial view is being called form the html helper, I would like to know is what would be the best way to populate the parital view with the model data.
Option 1: Inherit from parent page
By default, any partial view rendered by calling #Html.Partial("PartialViewName") will get the view model passed to the parent view.
So if you have:
View Model
namespace MyNamesapce
{
public OrderInfoViewModel
{
public string OrderTitle { get; set; }
public IEnumerable<OrderItem> OrderItems { get; set; }
}
}
OrderInfo.cshtml
#model MyNamespace.OrderInfoViewModel
<h1>#Model.OrderTitle</h1>
#Html.Partial("OrderLineItems")
The OrderLineItems page should get a MyNamespace.OrderViewModel passed to it... so your partial view should look like this:
OrderLineItems.cshtml
#model MyNamespace.OrderInfoViewModel
foreach (var orderItem in Model.OrderItems)
{
//Do stuff
}
Option 2: Specify model
You can use the second parameter to specify the view model to be passed. I.e.
OrderInfo.cshtml
#model MyNamespace.OrderInfoViewModel
<h1>#Model.OrderTitle</h1>
#Html.Partial("OrderLineItems", Model.OrderItems)
OrderLineItems.cshtml
#model IEnumerable<OrderItem>
foreach (var orderItem in Model)
{
//Do stuff
}
Option 3: Use partial actions
If you need to reuse a partial view over multiple pages, it could be a good idea to use a partial view to eliminate having to populate different view models with the same info just because the page is going to be using the same partial.
E.g.
View Model
namespace MyNamesapce
{
public OrderInfoViewModel
{
public string OrderTitle { get; set; }
}
}
Controller
public class OrderController : Controller
{
public ActionResult OrderInfo(int orderId)
{
OrderInfoViewModel viewModel = GetViewModel(orderId);
return View(viewModel);
}
public PartialViewResult OrderLineItems(int orderId)
{
IEnumerable<OrderItem> orderItems = GetOrderItems(orderId);
return Partial(orderItems);
}
}
OrderInfo.cshtml
#model MyNamespace.OrderInfoViewModel
<h1>#Model.OrderTitle</h1>
#Html.Action("OrderLineItems")
OrderLineItems.cshtml
#model IEnumerable<OrderItem>
foreach (var orderItem in Model.OrderItems)
{
//Do stuff
}
With a partial view, you are just sending in a Model just like you would with a normal View. For example, if your Model has a property of LineItem objects named 'LineItems' you simply would do this:
#Html.Partial("_PartialName", Model.LineItems)
Now if your Model does not have that property, you can either add it, or pass it another way, like ViewBag (I prefer a strongly typed method, but that is my opnion:
#Html.Partial("_PartialName", (List<LineItem>)ViewBag.LineItems)
These are not the only ways, but they are my preferred methods.

ASP.NET MVC - strongly typed view with partial views (view and partial views should also have access to some global data)

Consider the following scenario:
Action Edit() is forwarded to Edit.aspx view to render the view.
Edit.aspx consists of textbox1 and two partial views (aka view user controls):
part1.ascx (which has textbox2, textbox3)
and part2.ascx (which has checkbox1 and checkbox2)
You want to have a strongly typed view for Edit.aspx, say, you use EditViewData class.
You also need Edit.aspx, part1.ascx and part2.ascx have access to some global information such as currentUserID, currentUserLanguage, currentUserTimezone.
Questions:
How do you go about structuring the EditViewData class?
How do you pass the view data to the view and partial views so that the object gets populated automatically when you submit the form and return to the Edit() http.post action?
What do you pass to the Edit() http.post action?
Your viewdata should look like this:
public class EditViewData
{
public int currentUserID { get; set; }
public string currentUserLanguage { get; set; }
public string currentUserTimezone { get; set; }
// ... other stuff
}
After you strongly type your aspx, you also need to strongly type your ascxs. Then in your aspx, when you call RenderPartial, just call like usual:
<% using (Html.BeginForm()) %>
<% Html.RenderPartial("part1.ascx" ); %>
<% Html.RenderPartial("part2.ascx" ); %>
<%}%>
It should automatically inherit the Model in the control. Just remember that your BeginForm should be surrounding both of your controls (ascxs).

Resources