Christian Grabowski
Christian Grabowski

Reputation: 2892

Why isn't my razor code rendering?

I have some razor code for an MVC3 site that won't render. I'm getting a Cannot perform runtime binding on a null reference runtime error for some reason. Here is my view:

@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
<table>
    @for (var i = 0; i < ViewBag.taskList.Count; i++)
    {
        <tr>
            @for (var j = 0; j < 9; j++)
            {
                <td>@ViewBag.taskList.get(i).attr.get(j);</td>
            }
        </tr>
    }
</table>

Here is my model:

public class parentTask
{
    int id { get; set; }//task ID
    int pId { get; set; }//parent task ID
    String name { get; set; }//task name
    String dDate { get; set; }//due date
    String cDate { get; set; }//completion date
    String description { get; set; }//Description of task
    String assignedTo { get; set; }//assigned to
    String tags { get; set; }//tags
    public List<object> attr;//list for rendering attributes
    public parentTask(int i, int p, String n, String d, String c, String de, String a, String t)//constructor
    {
        id = i;
        pId = p;
        name = n;
        dDate = d;
        cDate = c;
        description = de;
        assignedTo = a;
        tags = t;
        attr= new List<object>();
        attr.Add(id);
        attr.Add(pId);
        attr.Add(name);
        attr.Add(dDate);
        attr.Add(cDate);
        attr.Add(description);
        attr.Add(assignedTo);
        attr.Add(tags);
    }
}

and here is my controller:

public class TaskController : Controller
{
    String[] values = new fileReader().values;
    public List<parentTask> taskList = new List<parentTask>();
    public ViewResult index(){
        String tId=values[0];
        String tPId=values[1];
        String tName=values[2];
        String tD=values[3];
        String tC=values[4];
        String tDe=values[5];
        String tA=values[6];
        String tT=values[7];
        for(int i=8; i< values.Length; i+=8){
            taskList.Add(new parentTask(Convert.ToInt32(values[i]), Convert.ToInt32(values[i + 1]), values[i + 2], values[i + 3], values[i + 4], values[i + 5], values[i + 6], values[i + 7]));
        }
        ViewBag.taskList = taskList;
        return View();
    }
    #region Status Codes
    private static string ErrorCodeToString(MembershipCreateStatus createStatus)
    {
        // See http://go.microsoft.com/fwlink/?LinkID=177550 for
        // a full list of status codes.
        switch (createStatus)
        {
            case MembershipCreateStatus.DuplicateUserName:
                return "User name already exists. Please enter a different user name.";

            case MembershipCreateStatus.DuplicateEmail:
                return "A user name for that e-mail address already exists. Please enter a different e-mail address.";

            case MembershipCreateStatus.InvalidPassword:
                return "The password provided is invalid. Please enter a valid password value.";

            case MembershipCreateStatus.InvalidEmail:
                return "The e-mail address provided is invalid. Please check the value and try again.";

            case MembershipCreateStatus.InvalidAnswer:
                return "The password retrieval answer provided is invalid. Please check the value and try again.";

            case MembershipCreateStatus.InvalidQuestion:
                return "The password retrieval question provided is invalid. Please check the value and try again.";

            case MembershipCreateStatus.InvalidUserName:
                return "The user name provided is invalid. Please check the value and try again.";

            case MembershipCreateStatus.ProviderError:
                return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

            case MembershipCreateStatus.UserRejected:
                return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";

            default:
                return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
        }
    }
    #endregion
}

When I run the program, it brings me to the view when the error is found, however I'm unsure where the problem lies so I figured I'd include the other code to help, which if anyone can help me, it'd be greatly appreciated.

Upvotes: 0

Views: 144

Answers (2)

iCollect.it Ltd
iCollect.it Ltd

Reputation: 93611

There are a number of issues with the code, so easiest to supply a complete example. I have gone with industry standard naming conventions for properties, variables and parameters.

View (strongly typed model):

Always aim to keep views as simple as possible as they are the least readable part of MVC. Use a strongly typed model in preference to ViewBag variables.

As the data is contained in lists, use foreach, rather than indexing them (both the tasks and the attributes in this case).

@model IEnumerable<TaskManager.Models.ParentTask>
@{
    ViewBag.Title = "Home Page";
}

<h2>@ViewBag.Message</h2>
<table>
    @foreach (var parentTask in Model)
    {
        <tr>
            @foreach (var attr in parentTask.Attr)
            {
                <td>@attr</td>
            }
        </tr>    
    }
</table>

Model:

Always go for readable variable/property/parameter names ahead of short names. Use of case allows you to reuse the names in a meaningful way as properties and matching parameters.

public class ParentTask
{
    int TaskId { get; set; }
    int ParentTaskId { get; set; }
    String TaskName { get; set; }
    String DueDate { get; set; }
    String CompletionDate { get; set; }
    String Description { get; set; }
    String AssignedTo { get; set; }
    String Tags { get; set; }

    public List<object> Attr;

    public ParentTask(int taskId, int parentTaskId, String taskName, String dueDate, String completionDate, String description, String assignedTo, String tags)//constructor
    {
        TaskId = taskId;
        ParentTaskId = parentTaskId;
        TaskName = taskName;
        DueDate = dueDate;
        CompletionDate = completionDate;
        Description = description;
        AssignedTo = assignedTo;
        Tags = tags;
        Attr = new List<object>();
        Attr.Add(TaskId);
        Attr.Add(ParentTaskId);
        Attr.Add(TaskName);
        Attr.Add(DueDate);
        Attr.Add(CompletionDate);
        Attr.Add(Description);
        Attr.Add(AssignedTo);
        Attr.Add(Tags);
    }
}

Controller (changed part):

You cannot guarantee the controller's constructor will be called once per page as they are reused, so you needed to clear your list of tasks each time.

public class TaskController : Controller
{
    String[] values = new fileReader().values;

    public List<ParentTask> TaskList = new List<ParentTask>();

    public ViewResult Index()
    {
        // These were not used
        //string tId = values[0];
        //string tPId = values[1];
        //string tName = values[2];
        //string tD = values[3];
        //string tC = values[4];
        //string tDe = values[5];
        //string tA = values[6];
        //string tT = values[7];

        // The constructor may not be called on each page load, so clear the list
        TaskList.Clear();
        for (int i = 8; i < values.Length; i += 8)
        {
            TaskList.Add(new ParentTask(Convert.ToInt32(values[i]), Convert.ToInt32(values[i + 1]), values[i + 2], values[i + 3], values[i + 4], values[i + 5], values[i + 6], values[i + 7]));
        }

        // Return a strongly typed view with our list of tasks as the ViewModel
        return View(TaskList);
    }

Upvotes: 1

ronish
ronish

Reputation: 568

Instead of using Viewbag to contains the parent task list return the view with the list itself.

In your controller:

return View(taskList)

Now in your view:

@model List<parentTask>

<h2>@ViewBag.Message</h2>
<table>
@for (var i = 0; i < Model.Count; i++)
{
    <tr>
        @for (var j = 0; j < 9; j++)
        {
            <td>@Model[i].attr[j];</td>
        }
    </tr>
}

Assuming that your class and other methods are error free.

Upvotes: 1

Related Questions