Object reference not set to an instance of an object - Partial View - asp.net-mvc

I have a strongly typed partial view which is giving me "Object reference not set to an instance of an object" error when I launch the master view. I know I am not passing in any parameters yet, but is there a way to handle this error?
Master View:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Test Form
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<div id="partial">
<% Html.RenderPartial("DisplayPartial"); %>
</div>
</asp:Content>
Partial View:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Student.Models.vwStudent>>" %>
<% foreach (var item in Model) {
if (item == null) continue; %>
<tr>
<td>
<%: item.Item1%>
</td>
<td>
<%: item.Item2%>
</td>
</tr>
<% } %>
</table>

You have to pass some Model to your partialView, because it need a instance of IEnumerable<Student.Models.vwStudent>
<% Html.RenderPartial("DisplayPartial", model); %>
Or, you can check in your partial view if the model is not null.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Student.Models.vwStudent>>" %>
<% if (Model != null) {
foreach (var item in Model) {
if (item == null) continue; %>
<tr>
<td>
<%: item.Item1%>
</td>
<td>
<%: item.Item2%>
</td>
</tr>
<% }
} %>
</table>

If you need to render this partial view when you don't have a Model, you can certainly test that Model is not null before the foreach loop
if (Model != null)
foreach (...)

Related

Why don't my form get posted correctly?

I am working on MVC POST/GET requests, but I observed some strange behavior.
My form is posted after editing it by clicking "Save" from browser, but when I received the request, all the attributes were undefined. CourseName, CourseCreditPts, Institute were null or zeros.
Code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(tblCourse a_Course)
{
// Retrieve existing object
var CourseToBeSaved = _pr.FindCourseById(a_Course.CourseID);
// without try-catch exception thrown
try
{
TryUpdateModel(CourseToBeSaved);
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
// Save
_pr.Save();
return View();
}
and the .aspx file containing code:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<DataWarehouse.tblCourse>" %>
<%# Import Namespace="DataWarehouse.Helpers" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit Course</h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<%: Html.HiddenFor(x=>x.CourseID) %>
<table>
<tr>
<td><b>Institute</b></td>
<td><%: Html.DropDownList("InstituteID")%> <%: Html.ValidationMessageFor(x=>x.InstituteID) %></td>
</tr>
<tr>
<td><b>CourseName</b></td>
<td><%: Html.TextBox("EditAbleCourseName")%> <%: Html.ValidationMessageFor(x => x.CourseName)%></td>
</tr>
<tr>
<td><b>CreditPoints</b></td>
<td><%: Html.TextBox("EditAbleCreditPoints")%> <%: Html.ValidationMessageFor(x => x.CreditPts)%></td>
</tr>
<tr>
<td><b>Status</b></td>
<td><%: Html.DropDownList("EditAbleStatus")%> <%: Html.ValidationMessageFor(x => x.Status)%></td>
</tr>
</table>
<p>
<input type="submit" value="Save" />
</p>
<% } %>
</asp:Content>
You didn’t post how the tblCourse class is defined, but from your validators it seems like it has a property called CourseName. You have named the textbox that should contain the course name EditAbleCourseName and there is your problem. For default model binding you have to name the inputs to the same name as the property on the class. This goes for your other properties too.
So try to rename your inputs to the same name as the properties on your class.
<%: Html.TextBox("CourseName")%>
and so on...

MVC: Form not rendering in partial view

I have a form with tabs. Subordinate to each tab is a partial view.
When the user submits to save changes, I want to call a method for that partial view, so for the partial view I put in <% using (Html.BeginForm(...) %>. But this gets ignored and clicking submit will call the method associated with the container view instead. Why is this, and how do I get this to work?
The View looks like;
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Employee.Master" Inherits="System.Web.Mvc.ViewPage<SHP.WebUI.Models.HolidayRequestViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
HolidayRequest
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="EmployeeContent" runat="server">
<% using (Html.BeginForm()) {%>
<%: Html.AntiForgeryToken() %>
<h2>Holiday Request</h2>
<p>You have <%: Html.DisplayFor(model => model.DaysAvailableThisYear) %> days left annual leave for this year
and <%: Html.DisplayFor(model => model.DaysAvailableNextYear) %> days left for next year.</p>
<p>If your request is approved and exceeds the number of days left, then those extra days will not be paid.</p>
<div id="tabs">
<ul>
<li>Approver</li>
<li>Single Date</li>
<li>Date Range</li>
</ul>
<div id="tabs-1">
<% Html.RenderPartial("GetApproverTab", Model); %>
</div>
<div id="tabs-2">
<% Html.RenderPartial("GetSingleDateTab", Model); %>
</div>
<div id="tabs-3">
<% Html.RenderPartial("GetDateRangeTab", Model); %>
</div>
</div>
<%: Html.HiddenFor(x => x.EmployeeId) %>
<% } %>
</asp:Content>
The partial view looks like;
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.WebUI.Models.HolidayRequestViewModel>" %>
<% using (Html.BeginForm("GetSingleDateTab", "Employee", FormMethod.Post, new { id = "frmSingleDate" }))
{ %>
<p>Enter your day or part day of Annual Leave here.</p>
<table>
<tr>
<td align="right">Date:</td>
<td><%: Html.EditorFor(x => x.SingleDate) %></td>
</tr>
<tr>
<td align="right">Morning Only:</td>
<td><%: Html.CheckBoxFor(x => x.MorningOnlyFlag) %></td>
</tr>
<tr>
<td align="right">Afternoon Only:</td>
<td><%: Html.CheckBoxFor(x => x.MorningOnlyFlag) %></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="Save" /></td>
</tr>
</table>
<% } %>
and the controller looks like;
#region Employee Holiday Request
public ActionResult HolidayRequest()
{
return View(new HolidayRequestViewModel(Employee.GetLoggedInUser().EmployeeId));
}
[HttpPost] // This is the method that gets executed
public ActionResult HolidayRequest(HolidayRequestViewModel hrvm)
{
if (ModelState.IsValid)
{
hrvm.Update();
return View(new HolidayRequestViewModel(hrvm.EmployeeId));
}
return View(hrvm);
}
[HttpPost] // This is the method I want to get executed.
public ActionResult GetSingleDateTab(HolidayRequestViewModel hrvm)
{
if (ModelState.IsValid)
{
hrvm.Update();
return View(new HolidayRequestViewModel(hrvm.EmployeeId));
}
return View("GetSingleDateTab", hrvm);
}
#endregion
You can't have nester forms in html.
I discover an unbelievable solution. Just insert a <script> tag above the <form> tag.
<script type="text/javascript">
// don't remove <script> tag
</script>
<form ....

MVC drop down list that controls a grid - what is the best way to get this to work?

I have a drop down list on the client side. When the user makes a selection, my jquery script extracts the new value of the selection.
But the code below does not work because I cannot work out how to send the selected value back to the controller. I am not sure about the syntax of sending the parameters as I am using paging parameters as it is. Maybe I should do an Ajax call instead?
The View looks like;
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
BankHoliday
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="AdminAccountsContent" runat="server">
<% using (Html.BeginForm())
{%>
<%: Html.AntiForgeryToken() %>
<h3>Bank Holiday Administration</h3>
<p>Select the year: <%: Html.DropDownListFor(model => model.SelectedYear, Model.YearList)%></p>
<fieldset>
<legend>Enter the bank holidays here:</legend>
<table>
<tr><td colspan="3"><i>You can find the bank holiday dates on this <a target="_blank" href="http://www.year-planner-calendar.wanadoo.co.uk/">website</a>.</i> </td></tr>
<tr>
<th>Bank Holiday</th>
<th>Date</th>
<th>Notes</th>
</tr>
<% foreach (var bankHolidayExtended in Model.BankHolidays)
{ %>
<% Html.RenderPartial("BankHolidaySummary", bankHolidayExtended); %>
<% } %>
<tr>
<td align="center" colspan="3" style="padding-top:20px;">
<input type="submit" value="Save"/>
</td>
</tr>
<% if (ViewData["UpdatedFlag"] == "True")
{ %>
<tr>
<td id="confirmationMessage" colspan="3">
At time <% Response.Write(DateTime.Now.ToString("T")); %> - Details have been successfully saved
</td>
</tr>
<%}
else if (ViewData["UpdatedFlag"] == "False")
{%>
<tr>
<td id="Td1" colspan="3">
At time <% Response.Write(DateTime.Now.ToString("T")); %> - ERROR! Details have NOT been saved
</td>
</tr>
<%} %>
</table>
</fieldset>
<% } %>
<script language="javascript" type="text/javascript">
$(function () {
$("#SelectedYear").change(function () {
var year = $("#SelectedYear").val();
$("#wholepage").load("/BankHoliday/Create/" + year);
});
});
</script>
</asp:Content>
and the Controller looks like;
public ActionResult ListHistory(GridSortOptions sort, int? page, int? EmployeeStatusId)
{
if (Request.QueryString["lastPersonMessage"] == null)
ViewData["LastPersonMessage"] = string.Empty;
else
ViewData["LastPersonMessage"] = Request.QueryString["lastPersonMessage"];
IEnumerable<EmployeeExtended> employees = null;
switch (EmployeeStatusId.GetValueOrDefault(1))
{
case 1: employees = EmployeeExtended.GetAllFormerEmployees();
break;
case 2: employees = EmployeeExtended.GetAllOnNoticeEmployees();
break;
case 3: employees = EmployeeExtended.GetAllCurrentEmployees();
break;
}
if (sort.Column != null)
{
employees = employees.OrderBy(sort.Column, sort.Direction);
}
int pageLength = Convert.ToInt32(ConfigurationManager.AppSettings["EmployeeListPageLength"].ToString());
employees = employees.AsPagination(page ?? 1, pageLength);
ViewData["sort"] = sort;
return View(employees);
}
You can it inside an Ajax.BeginForm() Call but the Url wouldn't change then.. - means: every time you refresh it, it'll return you back to the default page..
I already did something very similar to this:
<%: Html.DropDownList(Model => Model.SelectedYear, Model.YearList, new { onchange = "location.href='/Controller/Action/'+this.value" }) %>
This should provide some foundation on solving the issue.

MVC - fields in a partial View need a Unique Id. How do you do this?

In my view I render a partial view within a loop.
The problem I have is that for each new row, the Id of the fields remains the same.
I can I change this so that the Ids are unique and predictable?
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/AdminAccounts.master" Inherits="System.Web.Mvc.ViewPage<SHP.WebUI.Models.BankHolidayViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
BankHoliday
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="AdminAccountsContent" runat="server">
<% using (Html.BeginForm())
{%>
<h3>Bank Holiday Administration</h3>
<p>Select the year: <%: Html.DropDownListFor(model => model.SelectedYear, Model.YearList)%></p>
<fieldset>
<legend>Enter the bank holidays here:</legend>
<table>
<tr>
<th>Bank Holiday</th>
<th>Date</th>
<th>Notes</th>
</tr>
<% foreach (var bankHolidayExtended in Model.BankHolidays)
{ %>
<% Html.RenderPartial("BankHolidaySummary", bankHolidayExtended); %>
<% } %>
<tr>
<td align="center" colspan="3" style="padding-top:20px;">
<input type="submit" value="Create" />
</td>
</tr>
</table>
</fieldset>
<% } %>
Partial View
" %>
<tr>
<td><%: Model.T.BankHolidayDescription%></td>
<td><%: Html.EditorFor(model => model.BH.NullableBankHolidayDate)%></td>
<td><%: Html.EditorFor(model => model.BH.BankHolidayComment)%></td>
</tr>
I would recommend you using editor templates instead of rendering partial views:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/AdminAccounts.master" Inherits="System.Web.Mvc.ViewPage<SHP.WebUI.Models.BankHolidayViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
BankHoliday
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="AdminAccountsContent" runat="server">
<% using (Html.BeginForm()) { %>
<h3>Bank Holiday Administration</h3>
<p>Select the year: <%: Html.DropDownListFor(model => model.SelectedYear, Model.YearList)%></p>
<fieldset>
<legend>Enter the bank holidays here:</legend>
<table>
<tr>
<th>Bank Holiday</th>
<th>Date</th>
<th>Notes</th>
</tr>
<%: Html.EditorFor(x => x.BankHolidays) %>
<tr>
<td align="center" colspan="3" style="padding-top:20px;">
<input type="submit" value="Create" />
</td>
</tr>
</table>
</fieldset>
<% } %>
</asp:Content>
And then place your user control in ~/Views/Home/EditorTemplates/BankHolidayExtended.ascx (the name and location are important, replace Home with the name of your controller):
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.WebUI.Models.BankHolidayExtended>" %>
<tr>
<td><%: Model.T.BankHolidayDescription %></td>
<td><%: Html.EditorFor(model => model.BH.NullableBankHolidayDate) %></td>
<td><%: Html.EditorFor(model => model.BH.BankHolidayComment) %></td>
</tr>
This editor template will be automatically rendered for each element of the BankHolidays collection property on your view model. It will ensure that unique Ids are generated and the name of the input fields will be suitable for binding in the POST action. It also makes your code more readable.

MVC - Partial Views

I have a Viewpage menu with controller Menucontroller. I have a partialView ViewItems which is strongly typed as object BagItem with contro ller BagItem.
I am trying to render the partial View from View page(Menu.aspx) and can't render partial View. Any help would be greatly appreciated.New to MVC. Here is the code
Menu.aspx
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MenuItem>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
OrderMenu
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>
OrderMenu</h2>
<div>
<table>
<tr>
<td>
<% List<BagItem> sb = new List<BagItem>(); %>
<% Html.RenderPartial("../ShoppingBagItem/ViewItems", sb, (ViewDataDictionary)ViewData["BagItems"]);%>
</td>
</tr>
</table>
</div>
partialView
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<GuessCafe.Library.BagItem>>" %>
<body>
<div id="divLatestStocks">
<%foreach (var item in Model)
{ %>
<ul>
<li>
<%= item.ShoppingBagItemId %>
</li>
</ul>
<%}
%>
</div>
</body>
BagItemController
public ActionResult GetShoppingBagItems()
{
ViewData["BagItems"] = ObjectContext.BagItem.ToList();
return View(ViewData["BagItems"]);
}
I think what you want is simply this:
<% Html.RenderPartial("ViewItems", ViewData["BagItems"]); %>
This is assuming your partial view is named ViewItems.ascx.
You can remove the following line from your view:
<% List<BagItem> sb = new List<BagItem>(); %>
Update: your partial view should not contain <body>...</body> tags. These should either be on the master page.
public ActionResult GetShoppingBagItems()
{
ViewData["BagItems"] = ObjectContext.BagItem.ToList();
return View(ViewData["BagItems"]);
}
This is a bad practice at all. If you want pass Model to view why just use ViewData Dictionary ?
You can simply write :
public ActionResult GetShoppingBagItems()
{
var BagItems = ObjectContext.BagItem.ToList();
return View(BagItems);
}

Resources