Null reference exception error - asp.net-mvc

I have a Student data model(Entity Framework) where I have set both "StudentID" and "StudentName" as primary keys. StudentID is of type Int and StudentName is of type String.
I created a strongly-typed view, But when I run it i get the following error:
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 10: <tr>
Line 11: <td>
Line 12: <%= Html.Encode(item.StudentID) %>**
Line 13: </td>
Line 14: <td>
Here is my controller action:
public ActionResult Index()
{
ViewData.Model = student.StudentTable;
return View();
}
Here is the View:
<%# Page
Language="C#"
Inherits="System.Web.Mvc.ViewPage<IEnumerable<Student.Models.StudentTable>>" %>
<html>
<head runat="server">
</head>
<body>
<table>
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.Encode(item.StudentID) %>
</td>
<td>
<%= Html.Encode(item.StudentName) %>
</td>
</tr>
<% } %>
</table>
</body>
</html>

Without any additional information, my guess is that item is null. If the Student Table has a SINGLE StudentID per record, then you need to simply pass model.StudentID
Controller
public ActionResult Index()
{
var model = student.StudentTable;
return View(model);
}
aspx
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.Encode(item.StudentID) %>
</td>
<td>
<%= Html.Encode(item.StudentName) %>
</td>
</tr>
<% } %>

I doubt item is null, if it were null you wouldn't get inside the loop. Set a break point and examine item, it's probably not what you think it is.

If this is the line you're getting the exception on, then your item variable must be null. You'll need to look closely at how that's being populated - if your model is null, then you should be able to throw a debugger on your controller action and figure out why that's not working.

Could be a few things ...
Are you passing up valid view data from the ActionMethod?
Have you defined #model on the view?
Assuming student.StudentTable is a single object with StudentID property then you need to change your view code to Model.StudentID

Related

How to update different targets with MVC Ajax helper?

i'm having a hard time dealing with MVC Ajax helper and trying to refresh certain part of the page. In my code, I have a situation like this:
<div id="ajaxLoadedContent">
<table>
<tr>
<th>
<%: Html.Label("ProductId") %>
</th>
<th>
<%: Html.Label("ProductName") %>
</th>
<th>
</th>
</tr>
<% foreach (var product in Model.Products)
{
%>
<tr>
<td>
<%: direccion.ProductId %>
</td>
<td>
<%: direccion.ProductName %>
</td>
<td>
<% using (Ajax.BeginForm("EditProduct", "MyController",
new { ContainerDiv = "ShowEditProducts" },
new AjaxOptions() { UpdateTargetId = "ShowEditProducts", OnSuccess = "updatePlaceholder" }))
{%>
<%: Html.Hidden("ProductId", product.ProductId)%>
<input type="submit" value="Edit" />
<%} %>
</td>
</tr>
<% } %>
</table>
<script type="text/javascript">
function updatePlaceholder(context) {
var html = context.get_data();
var placeholder = context.get_updateTarget();
$(placeholder).html(html);
return false;
}
</script>
<div id="ShowEditProducts"></div>
</div>
Now, when I press the Edit button, then the 'Editor View' appears, but the problem is that when i Submit that form, then there are two options:
The data is OK, the changes are made, the form dissapears and the list is refreshed.
The data is NOT OK, the forms stays and the validation messages appear.
The problem is that the UpdateTargetId are different for each option.
Option 1 refreshes "ShowEditProducts", while Option 2 refreshes "ajaxLoadedContent". Also, ehe 'Edit View' contains JavaScript that is executed when the view is loaded using the "Edit" button but is not executed when the form contains errors and is re-rendered.
The code of the EditView looks like this:
<% using (Ajax.BeginForm("SubmitEdit", new AjaxOptions() { UpdateTargetId = Model.ContainerDiv}))
{%>
<script type="text/javascript">
// My JavaScript
</script>
<table>
<tr>
<td>
<%: Html.Label("Id")%></br>
<%: Html.TextBoxFor(x => x.Product.ProductId)%></br>
</td>
<td>
<%: Html.Label("Name")%></br>
<%: Html.TextBoxFor(x => x.Product.ProductName)%><
</td>
</tr>
</table>
<input type="submit" value="Save" />
<%: Ajax.ActionLink("Cancel", "EmptyView","Shared", new AjaxOptions() { UpdateTargetId = Model.ContainerDiv})%>
<% } %>
So, now my two big problems are:
1. The JavaScript of the 'Edit View' don't get executed when the the view is re-renderd.
2. How can i update one target is there are errors and another one when there are not.
Thanks
The object being replaced is being set on this line:
var placeholder = context.get_updateTarget();
So instead, you should add a condition here. Eg, instead of returning HTML directly, if you return an object that looks like this:
public class Result
{
public bool Success { get; set; }
public string Html { get; set; }
}
Then you could do something like this:
var result = response.get_response().get_object();
if (result.Success)
$("#ShowEditProducts").html(html);
else
$("#ajaxLoadedContent").html(html);
Alternatively, instead of returning a Success boolean, you could have a property for the ID of the control to replace. This would be more reusable, and might make sense if you want the decision of which control to replace to be done server-side.

ajax.beginform inside a for loop

so I am using a foreach loop to iterate through comments. The comment section is wrapped inside "Comments" div. My function DeleteComment fetches comments again once you delete a comment and rebinds it to the control. However, after you delete a comment, anytime you try to delete another comment, the commentId of the very first deleted comment would keep getting passed to DeleteComment function instead of the passing the commentId of the comment you are trying to delete. If you refresh the page, then you can delete ONE comment again, and the same problem if you try to delete another.
<table>
<% foreach (var item in Model) { %>
<tr> <td>item.Comment </td>
<td>
<%if (HttpContext.Current.User.Identity.IsAuthenticated && item.Poster.UserName == HttpContext.Current.User.Identity.Name)
{ %>
<%using (Ajax.BeginForm("DeleteComment", "Home", new AjaxOptions {UpdateTargetId = "Comments"}))
{%>
<%=Html.Hidden("articleId", item.CarrierId) %>
<%=Html.Hidden("num_comments", (int)ViewData["num_comments"]) %>
<%=Html.Hidden("commentId", item.CommentId) %>
<input type = "submit" value = "delete" />
<%} %>
<%} %>
</td>
</tr>
<table>
For example, you delete comment with commentId 1... then you try to delete some other comment, but commentId 1 would keep getting passed. You refresh the page, problem gone... for one comment...
<div id = "Comments">
<%if ((int)ViewData["num_comments"] > 0)
{ %>
<%Html.RenderPartial("CommentsX", Model.Comments, new ViewDataDictionary{{"num_comments", ViewData["num_comments"] }}); %>
<%} %>
</div>
where CommentsX is the ascx control that contains the for loop code I posted above.
Sometimes having multiple elements on the same page with the same ids can cause funky results like you are seeing. Try making the id's unique like below:
<table>
<% int index=1;
foreach (var item in Model) { %>
<tr> <td>item.Comment </td>
<td>
<%if (HttpContext.Current.User.Identity.IsAuthenticated && item.Poster.UserName == HttpContext.Current.User.Identity.Name)
{ %>
<%using (Ajax.BeginForm("DeleteComment", "Home", new AjaxOptions {UpdateTargetId = "Comments"}))
{%>
<%=Html.Hidden("articleId" + index, item.CarrierId) %>
<%=Html.Hidden("num_comments" + index, (int)ViewData["num_comments"]) %>
<%=Html.Hidden("commentId" + index, item.CommentId) %>
<input type = "submit" value = "delete" />
<%} %>
<% index++;
} %>
</td>
</tr>
<table>

MVC - Ajax form - return partial view doesnt update in <div> target

I have an index view that I want to update automatically as the user types in a client id. I got something similiar to work (only it was updating just a label) - but this will not work.
What happens is the partial is just rendered by itself (not in place of the UpdateTargetID). So the data is rendered on a new page. Here is my code:
Controller:
public ActionResult ClientList(string queryText)
{
var clients = CR.GetClientLike(queryText);
return PartialView("ClientIndex", clients);
}
Partial View:
<table>
<thead>
<tr>
<td>Client ID</td>
<td>Phone1</td>
<td>Phone2</td>
<td>Phone3</td>
<td>Phone4</td>
</tr>
</thead>
<tbody>
<% if (Model != null)
{
foreach (Client c in Model)
{ %>
<tr>
<td><%= Html.Encode(c.ClientID)%></td>
<td><%= Html.Encode(c.WorkPhone)%></td>
<td><%= Html.Encode(c.WorkPhone1)%></td>
<td><%= Html.Encode(c.WorkPhone2)%></td>
<td><%= Html.Encode(c.WorkPhone3)%></td>
</tr>
<% }
} %>
</tbody>
Main View:
Insert code messed up, so this is just copy/pasted:
$(function() {
$("#queryText").keyup(function() {
$('#sForm').submit();
});
});
<div id="status" class="status" name="status">
<%--<% Html.RenderPartial("ClientIndex", ViewData["clients"]); %> Should this be here???? --%>
</div>
I had the same problem.
In my partial view, I had this
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
but it should have been this
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IQueryable<Client>>" %>
an easy way to test if your ajax call is working is to return a string instead of an ActionResult
public string ClientList(string queryText)<
{
return("ok, the ajax call must have worked because I see this string.");
}
Rather than posting a form on the page constantly why not do a behind the scenes jQuery.get call to get the search results for the provided text. I would think this would be faster and cleaner. When submitting the form like I think you are (judging from my reading of your code) you are causing the page to essentially refresh (and not re-write to the div).
$('#sForm').submit()

Proper submission of forms with autogenerated controls

Based on:
MVC Html.CheckBox and form submit issue
Let's consider following example. View:
<% using(Html.BeginForm("Retrieve", "Home")) %>
<% { %>
<%foreach (var app in newApps) { %>
<tr>
<td><%=Html.CheckBox(""+app.ApplicationId )%></td>
</tr>
<%} %>
<input type"submit"/>
<% } %>
Controller:
List<app>=newApps; //Database bind
for(int i=0; i<app.Count;i++)
{
var checkbox=Request.Form[""+app[i].ApplicationId];
if(checkbox!="false")// if not false then true,false is returned
}
Proposed solution was about manual parsing of Request.Form that seems for me out of MVC concept. It makes the problem while unit testing of this controller method. In this case I need to generate mock Request.Form object instead of some ViewModel passed as input param.
Q: Is there some other solution of submitting forms like this, so that ViewModel object, containing collection of submitted controls, passed as input param to controller method?
For example:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Retrieve(AppList[] applist)
or
public ActionResult Retrieve(AppList<App> applist)
etc
Controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Retrieve(AppList[] applist)
View:
<% using(Html.BeginForm("Retrieve", "Home")) %> { %>
<%foreach (var app in newApps) { %>
<tr>
<td><%=Html.CheckBox(String.Format("appList[{0}].AProperty", app.ApplicationId) %></td>
</tr>
<% } %>
<input type"submit" />
<% } %>
Read this: Scott Hanselman's ComputerZen.com - ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries
UPDATED:
If ApplicationId is a key from DB it is better to use AppList<App> as Action parameter. Then your form would be looking as:
<% using(Html.BeginForm("Retrieve", "Home")) %> { %>
<% var counter = 0; %>
<% foreach (var app in newApps) { %>
<tr>
<td><%=Html.CheckBox(String.Format("appList[{0}].Key", counter), app.ApplicationId) %></td>
<!-- ... -->
<td><%=Html.Input(String.Format("appList[{0}].Value.SomeProperty1", counter), app.SomeProperty1) %></td>
<td><%=Html.Input(String.Format("appList[{0}].Value.SomePropertyN", counter), app.SomePropertyN) %></td>
<% counter = counter + 1; %>
</tr>
<% } %>
<input type"submit" />
<% } %>

Ajax.ActionLink, how to send the selected object in the partial view? asp.net mvc

I guess this is a noob question, but here it comes:
I have a list of products:
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.Encode(item.code) %>
</td>
<td>
<%= Html.Encode(String.Format("{0:g}", item.date)) %>
</td>
<td>
<%= Html.Encode(item.category) %>
</td>
<td>
<%= Html.Encode(item.description) %>
</td>
<td>
<%= Html.Encode(String.Format("{0:F}", item.price)) %>
</td>
......
}
And a partial view after all of these (in the same page):
<div id="productForEdit">
<fieldset>
<legend>Your Selected Product</legend>
<% Html.RenderPartial("~/Views/Products/Edit", productObject); %>
</fieldset>
</div>
How do I use Ajax.ActionLink, so that when I will click the description of a product, the product will be plugged in the Partial View from the bottom of the page?
I tried some combination with UpdateTargetId="productForEdit", but I had no success.
The purpose is to have a quick edit tool in the page.
I think this should work:
<td>
<%= Ajax.ActionLink(Html.Encode(item.description), /* link text */
"GetProduct", /* action name */
"Product", /* controller name */
new { productCode = Model.code }, /* route values */
new AjaxOptions() { InsertionMode = InsertionMode.Replace,
UpdateTargetId = "productForEdit" }) %>
</td>
This does expect a ProductController with an action named GetProduct, which takes a parameter productCode. Have this action return the view "Products/Edit".
You could also pass the whole product as a parameter to the action method, but that changes nothing to the basic idea. Good luck!

Resources