I have an ASP.NET MVC project that works fine on my local machine (no build errors, server errors or anything). However, when I publish the project to a test server, I get an "Object reference not set to an instance of an object" error on a For Each
I have in my view.
I have a function within a model that returns a DataRowCollection. I'm calling that function in my controller and passing the DataRowCollection to my View, which then iterates over the rows and displays the necessary information:
In the Controller I have:
Function Index()开发者_如何学运维 As ActionResult
Dim MyModel As New Model
ViewData("MyDataRowCollection") = MyModel.GetDataRowCollection()
Return View()
End Function
And then in the View, which is throwing the error:
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
My Page Title
</asp:Content>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<%
For Each MyDataRow In ViewData("MyDataRowCollection")
' do stuff with each MyDataRow
Next
%>
I'm pretty new to ASP.NET MVC so I'm sure there might be a better way to do what I'm doing (I'd be happy to hear if there is), but my main concern is why this works fine on my local machine but throws an error on the For Each
on the test server?
Please let me know if I can clarify any of the above, and thanks in advance for any information.
Obviously, the ViewData is not populated, so ViewData("MyDataRowCollection") returns null, which throws exception. The code from your controller would help to figure out what's happening.
EDIT :
I don't see anything wrong with your controller either. It's so simple as well, I doubt that the problem comes from here... probably deeper into your GetData method.
Anyway, You might want use strongly typed views instead of generic ones. strongly typed views inherit from ViewPage(Of T) instead of just ViewPage. That way you pass a model class of type T to your view and you access it in a strongly typed manner.
Also instead of passing directly the datarows, you should make the big work inside your controller and return a List easy to manipulate in your view.
Keep your view as dumb as possible.
Function Index() As ActionResult
Dim MyModel As New Model
Dim MyViewModel As New ViewModel
MyViewModel.Rows = MyModel.GetDataRowCollection()
var MyViewModel = MyModel.GetDataRowCollection()
Return View(MyViewModel)
End Function
and your view:
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyViewModel>" %>
...
<%
For Each MyDataRow In Model.Rows
' do stuff with each MyDataRow
Next
%>
That way you could also write tests on your controller and assert what your Model class contains, and not try to see if the HTML contains the correct results...
I will pass the deep explanation as you can find this all over the internet, but with some work to mock away your dependencies, you can then write something like this (I'm not really a VB guru, so excuse my syntax)
Dim Controller As New HomeController
Dim Result = Controller.Index()
Assert.IsNotNull(Result.Model)
精彩评论