2

I have a web application with this controller:

    public class ServiceRequestController : Controller
    {

    [Authorize(Roles = "Customer")]
    public ActionResult Create()
    {
        return View();
    }

    [Authorize(Roles = "Customer")]
    public ActionResult CreateNewUserAccount()
    {
        return View();
    }

    [Authorize(Roles = "Customer")]
    [HttpPost]
    public ActionResult CreateNewUserAccount(ServiceRequest serviceRequest)
    {
        if (ModelState.IsValid)
        {
            serviceRequest.Log.Id = User.Identity.GetUserId().ToString();
            serviceRequest.Log.DateTimeLogged = System.DateTime.Now;
            serviceRequest.LogID = db.Logs.Max(item => item.LogID);
            serviceRequest.EstimatedResolveDate serviceRequest.CalculateEstimatedResolveDate();
            db.ServiceRequests.Add(serviceRequest);
            db.SaveChanges();
            return RedirectToAction("AllServiceRequests", "Log");
        }
        return View(serviceRequest);
    }

The serviceRequest.Log.Id = User.Identity.GetUserId().ToString(); (And any preceding line if this is commented out) throws a null reference exception. I presume the serviceRequest is somehow null?

The ActionLink which requests the CreateNewUserAccount() page is:

@Html.ActionLink("New User Account", "CreateNewUserAccount", "ServiceRequest")

I'm not sure how to resolve this exception?

The model is:

public partial class ServiceRequest
{
    public int ServiceRequestID { get; set; }
    public Nullable<int> LogID { get; set; }
    public string RequestType { get; set; }
    [DisplayName("Additional Information")]
    [Required]
    [StringLength(200)]
    public string AdditionalInformation { get; set; }
    public DateTime EstimatedResolveDate { get; set; }

    [Required]
    [DisplayName("Delivery Date")]
    public DateTime DeliveryDate { get; set; }

    public virtual Log Log { get; set; }


    public DateTime CalculateEstimatedResolveDate()
    {
        return System.DateTime.Now.AddDays(3);
    }

}

View code:

@model OfficiumWebApp.Models.ServiceRequest

@{
ViewBag.Title = "New User Account";
}
@using(Html.BeginForm("CreateNewUserAccount", "ServiceRequest", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
    @Html.ValidationSummary(true)

    <div class="form-group">
        @Html.LabelFor(model => model.RequestType, new { @class = "control-label col-md-2" })
        <div class="col-md-3">
            <div class="editor-field">
                @Html.TextBoxFor(model => model.RequestType, new { @Value = ViewBag.Title, @readonly = "readonly" })
                @Html.ValidationMessageFor(model => model.RequestType)
            </div>
        </div>
    </div>

    <div class="form-group">
        @Html.Label("Name of Account Holder", new { @class = "control-label col-md-2" })
        <div class="col-md-3">
            <div class="editor-field">
                @Html.TextBox("AccountName")
                @Html.ValidationMessageFor(model => model.RequestType)
            </div>
        </div>
    </div>

   <div class="form-group">
    @Html.Label("Department", new { @class = "control-label col-md-2" })
    <div class="col-md-3">
        <div class="editor-field">
            @Html.TextBox("Department")
            @Html.ValidationMessageFor(model => model.RequestType)
        </div>
    </div>
</div>

<div class="form-group">
        @Html.Label("Location", new { @class = "control-label col-md-2" })
        <div class="col-md-3">
            <div class="editor-field">
                @Html.TextBox("Location", null, new { id = "Location" }))
                @Html.ValidationMessageFor(model => model.RequestType)
            </div>
        </div>
    </div>


    <div class="form-group">
        @Html.LabelFor(model => model.AdditionalInformation, new { @class = "control-label col-md-2" })
        <div class="tags">
            <div class="col-md-10">
                @Html.TextAreaFor(model => model.AdditionalInformation)
                @Html.ValidationMessageFor(model => model.AdditionalInformation)
            </div>
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.DeliveryDate, new { @id = "VisitDateLabel", @class = "control-label col-md-2" })
        <div class="col-md-3">
            <div class="editor-field">
                @Html.JQueryUI().DatepickerFor(model => model.DeliveryDate).Inline(false)
                @Html.ValidationMessageFor(model => model.DeliveryDate)
            </div>
        </div>
    </div>
        <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-floppy-save"></span></button>
        </div>
    </div>
</div>
}
John Saunders
  • 157,405
  • 24
  • 229
  • 388
ASPCoder1450
  • 1,551
  • 4
  • 21
  • 44

1 Answers1

2

You need to return the view i.e.

[Authorize(Roles = "Customer")]
public ActionResult CreateNewUserAccount()
{
    var model = new ServiceRequest();
    model.Log = new Log();
    return View(model);
}

In your view you need to add a model reference too at the top i.e.

@model ServiceRequest

You could also initialise the Log object in your model as follows:

public class ServiceRequest
{
    public ServiceRequest()
    {
       Log = new Log();
    }

    ....
}

An action link will not post your model back, you need to include it within a form and include all the model values that you want to be updated on the client i.e.

@using (Html.BeginForm("CreateNewUserAccount", "ServiceRequest", FormMethod.Post)){

  @Html.EditorFor(m => m.AdditionalInformation)
  ...
  <input type="submit" value="submit" />

Update

Taken from the below comments, this was resolved by creating a new log on post i.e.

 var log = new Log { 
   Id = User.Identity.GetUserId().ToString(), 
   DateTimeLogged = System.DateTime.Now, 
   LogID = db.Logs.Max(item => item.LogID) }; 
 serviceRequest.Log = log;
hutchonoid
  • 31,459
  • 14
  • 91
  • 100
  • Ok. I did the first change but it made no difference. The second I already had and the 3rd I already have 'public virtual Log Log { get; set; }' this in the ServiceRequest class – ASPCoder1450 Feb 24 '14 at 21:13
  • @ASPCoder1450 Hi, did you also see my update with the form too? :) – hutchonoid Feb 24 '14 at 21:21
  • @hutconoid yes i've added this in now but can confirm its made no difference – ASPCoder1450 Feb 24 '14 at 21:29
  • @ASPCoder1450 I think because you are not populating the ServiceRequest from the db initially. You should just be able to initialise it as follows in your get; model.Log = new Log(); I added that to the beginning of the question. I'm taking it that the User.Identity is populated as you are authenticated already. – hutchonoid Feb 24 '14 at 21:49
  • Ok I've also added this and its made no difference :( – ASPCoder1450 Feb 25 '14 at 12:54
  • 1
    @ASPCoder1450 How about just creating a new log on post i.e. var log = new Log { Id = User.Identity.GetUserId().ToString(), DateTimeLogged = System.DateTime.Now, LogID = db.Logs.Max(item => item.LogID) }; serviceRequest.Log = log; – hutchonoid Feb 25 '14 at 13:00
  • @ASPCoder1450 No problem, get there in the end. Will add the resolution to the answer. :) – hutchonoid Feb 25 '14 at 13:10