locked
Help with error RRS feed

  • Question

  • User627490255 posted

    Hi all, i have a webapp my brother in law helped me build it (well he did it all..then has largely left me too it), i am new to programming c#, http, css etc. ai have a little sporadic experience with python and vb,net.

    anyway, i have an 'object not set to an instance of an object error when submit button is hit. 

    i have noted where the code resides.

    In views/incident/editincident.cshtml
    
    @model CareHomeForms.Models.EditIncidentViewModel
    <!-- The heading title for the page -->
    <div class="row">
    	<div class="col-sm-12">
    		<h1>Report a new incident</h1>
    	</div>
    </div>
     
    <div class="row">
    	<div class="col-sm-12">
    		<h2 class="alert">General Details</h2>
    	</div>
    </div>
     
    <div class="row">
    	<div class="col-sm-12">
    		<form action="@Url.Action("EditIncident","Incident")" method="post" class="form-horizontal">
    			@Html.AntiForgeryToken()
     
    			<div class="form-group">
    				<label for="IncidentNumber" class=" control-label col-sm-3">Incident Number</label>
    				<div class="col-sm-1">
    					<input type="text" name="IncidentNumber" id="IncidentNumber" value="@Model.IncidentNumber"
    						   readonly class="form-control" data-toggle="popover"
    						   data-content="Generated Automaticaly"
    						   data-trigger="focus" data-placement="top" />
    				</div>
    			</div>
    <div class="form-group">
    				<div class="col-sm-12">
    					<button type="submit" name="Submit" class="btn btn-success pull-right">Create Incident</button>
    				</div>
    			</div>
     
    			<div class="form-group">
    				<div class="col-sm-12">
    					<a href="@Url.Action("","")" class="btn btn-default">Cancel &amp; Return To Home Page</a>.
    				</div>
    			</div>
    		</form>
    In root of controlers folder
    
    using CareHomeForms.Models;
    using CareHomeForms.Services.Data;
    using CareHomeForms.Services.Data.Models;
    using Microsoft.AspNetCore.Mvc;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
     
    namespace CareHomeForms.Controllers
    {
    	[Route("incident")]
    	public class IncidentController : Controller
    	{
    		private ICareHomesDb db;
     
    		
    		public IncidentController(ICareHomesDb db)
    		{
    			this.db = db;
    		}
     
    		[Route("New")] //    The name of the function 
    		[HttpGet]
    		[Authorize(Roles = "admin")]
    		public ActionResult NewIncident(EditIncidentViewModel viewModel, string id = null) //   what is passed to it in brackets
    		{
    			var newId = id ?? Guid.NewGuid().ToString();                               //     generate a new guid for the new form
    				
    			return RedirectToAction("EditIncident", new {incidentId = newId});  //   this redirects to another function 'editincident' with the viewmodel and new id
    		}
     
     
    		[Route("{incidentId}/edit")]//request received for the incident report form
    		[HttpGet]
    		public async Task<ActionResult> EditIncident() //The view name
    		{
    			var employeeResults = await db.GetPeopleAsync(PersonType.Employee);
    			var employees = employeeResults.ToList();
    			employees.Insert(0, new Person());
     
    			var residentsResults = await db.GetPeopleAsync(PersonType.Resident);
    			var residents = residentsResults.ToList();
    			residents.Insert(0, new Person());
     
    			var viewModel = new EditIncidentViewModel
    			{
    				IncidentNumber = "1234",
    				Staff = ToIdentifiedPerson(employees),
    				Residents = ToIdentifiedPerson(residents)
    			};
     
    			return View(viewModel);
    		}
     
    		//// This action will respond to a POST request from a form being submitted
    		[Route("{incidentId}/edit")]
    		[HttpPost] //do something when a form has been sent (posted) back
    		[ValidateAntiForgeryToken]
    		public async Task<ActionResult> FormSubmitted(EditIncidentViewModel viewModel, string returnUrl = null)
    		{
     
    			bool isUpdate = true;
    			var incident = await db.GetIncidentFormByIdAsync(viewModel.Incident.Id);
     
    			if (incident == null)
    			{
    				incident = viewModel.Incident;
    				incident.Version = 1;
    				incident.IsDraft = false;
    			}
    			else
    			{
    				isUpdate = false;
    			}
     
    			incident.LastUpdated = DateTime.UtcNow;
    			incident.Author = "5E5D44AF-2B72-4F7D-AC95-F99530E2752D";
     
    			await db.SaveIncident(incident, isUpdate);
     
    		return RedirectToAction("FormSubmitted", new { viewModel.Incident.Id, returnUrl });
    		}
     
    In root of models folder
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using CareHomeForms.Models;
    using CareHomeForms.Services.Data.Models.FormModels;
     
    namespace CareHomeForms.Models
    { 
    	public class EditIncidentViewModel
    	{
    		public List<IdentifiedPerson> Staff { get; set; }
    		public Incident Incident { get; set; }
    		public List<IdentifiedPerson> Residents { get; set; }
    		public string IncidentNumber { get; set; }
    		public string IncidentId { get; internal set; }
    		public string Id { get; internal set; }
     public string ReportingStaffId { get; set; }
    		public bool IsUpdate { get; set; }
    	}
    }
    
    
    

    Any help with this error appreciated:-)

    Error – NullReferenceException: Object reference not set to an instance of an object. • CareHomeForms.Controllers.IncidentController.FormSubmitted(EditIncidentViewModel viewModel, string returnUrl) in IncidentController.cs + 67. var incident = await db.GetIncidentFormByIdAsync(viewModel.Incident.Id);

    cheers

    steve

    Wednesday, September 18, 2019 6:57 AM

All replies

  • User197322208 posted

    Technical:

    Is normal that this line gives error in POST

    var incident = await db.GetIncidentFormByIdAsync(viewModel.Incident.Id);

    because , in the view,  there are not posting any field that is Incident.Id

    What should be this id taken from ?

    It is, by any chance, 

    <input type="text" name="IncidentNumber"

    ?

    Wednesday, September 18, 2019 2:43 PM
  • User627490255 posted

    Good point....I am pretty much copying and pasting from a very similar form, and trying to figure out how it all clicks together. I will post the view from that and maybe you could help me understand why that one works and this doesn't?

    @model CareHomeForms.Models.EditDocumentViewModel
    
    @{
    	ViewData["Title"] = "Document Editor";
    }
    
    @section HeadScripts
    {
    	<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
    	<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
    }
    
    <div class="row">
    	<div class="col-sm-12">
    		<h2>@(Model.IsUpdate ? "Edit Document" : "New Document")</h2> 
    	</div>
    </div>
    
    <div class="row">
    	<div class="col-sm-12">
    		<form class="form-horizontal" action="@Url.Action("EditDocument", new { returnUrl = Model.ReturnUrl })" method="post">
    			@Html.AntiForgeryToken()
    			<input type="hidden" name="Document.Id" value="@Model.Document.Id" />
    			<input type="hidden" name="Document.DocumentType" value="@Model.Document.DocumentType" />
    			
    
    			<div class="form-group">
    				<input type="text" value="@Model.Document.Title" placeholder="Title" name="Document.Title" class="form-control" />
    			</div>
    
    			<div class="form-group">
    				<textarea class="form-control" rows="40" name="Document.DocumentText" id="txtDocument">@Model.Document.DocumentText</textarea>
    			</div>
    
    			<div class="form-group">
    				<a href="@Model.ReturnUrl" class="btn btn-danger">Cancel</a>
    				<button type="submit" class="btn btn-success pull-right">Save</button>
    			</div>
    		</form>
    	</div>
    </div>
    
    <section Scripts>
    	<script>
    		var editor = new SimpleMDE({ element: document.getElementById("txtDocument") });
    	</script>
    </section>

    Wednesday, September 18, 2019 5:48 PM
  • User-17257777 posted

    Hi greenblood,

    <input type="text" name="IncidentNumber" id="IncidentNumber"

    The first form only has one input(name="IncidentNumber") that will be sent to the controller, so the "Incident " in "EditIncidentViewModel" will be null. 

    var incident = await db.GetIncidentFormByIdAsync(viewModel.Incident.Id);

    And you want to get the "id" from a null Object, it will certainly give the error. 

    Best Regards,

    Jiadong Meng

    Friday, September 20, 2019 8:52 AM
  • User627490255 posted

    Hi, Thanks for the help.

    But there is a hidden field for incident.id -  

    <input type="hidden" name="Incident.Id" value="@Model.Incident.Id" />

    When run with a break, there's no object being passed back to the controller.

    Friday, September 20, 2019 1:14 PM
  • User197322208 posted

    But there is a hidden field for incident.id -  

    <input type="hidden" name="Incident.Id" value="@Model.Incident.Id" />

    I do not see in the original post

    <form class="form-horizontal" action="@Url.Action("EditDocument", new { returnUrl = Model.ReturnUrl })" method="post">
    			@Html.AntiForgeryToken()
    			<input type="hidden" name="Document.Id" value="@Model.Document.Id" />
    			<input type="hidden" name="Document.DocumentType" value="@Model.Document.DocumentType" />
    			
    
    			<div class="form-group">
    				<input type="text" value="@Model.Document.Title" placeholder="Title" name="Document.Title" class="form-control" />
    			</div>
    
    			<div class="form-group">
    				<textarea class="form-control" rows="40" name="Document.DocumentText" id="txtDocument">@Model.Document.DocumentText</textarea>
    			</div>
    
    			<div class="form-group">
    				<a href="@Model.ReturnUrl" class="btn btn-danger">Cancel</a>
    				<button type="submit" class="btn btn-success pull-right">Save</button>
    			</div>
    		</form>

    Friday, September 20, 2019 2:22 PM
  • User627490255 posted

    Ah no, that's the second post I made, with the code I'm copying for reference. That mvc combo works fine.

    heres the post function for that mvc.

    		[Route("{documentId}/edit")]																//data recieved from webpage {documentid}/edit
    		[HttpPost]
    		[ValidateAntiForgeryToken]
    		[Authorize(Roles = "admin")]																			//only admin level can edit
    		public async Task<ActionResult> EditDocument(EditDocumentViewModel viewModel, string returnUrl = null)			//function name EditDocument
    		{
    			returnUrl = GetReturnUrl(returnUrl);
    
    			bool isUpdate = false;
    			var document = await db.GetDocumentByIdAsync(viewModel.Document.Id);								//see if there is a document in the db with this id
    
    			if (document == null)
    			{
    				document = viewModel.Document;																//if not, create new document
    				document.Version = 1;																		//give it a version 1 number
    				document.IsDraft = false;
    			}
    			else
    																											//if there is a document with this id, 
    			{
    				document.DocumentText = viewModel.Document.DocumentText;									//update document details and mark as updated
    				document.Title = viewModel.Document.Title;
    				isUpdate = true;
    			}
    
    			document.LastUpdated = DateTime.UtcNow;
    
    			document.Author = User.FindFirst(ClaimTypes.NameIdentifier).Value;//"5E5D44AF-2B72-4F7D-AC95-F99530E2752D";         assign author as the logged in person
    
    			await db.SaveDocument(document, isUpdate);														//save the document to the db
    
    			return RedirectToAction("ShowDocument", new { viewModel.Document.Id, returnUrl });
    		}
    

    and the model-

    using CareHomeForms.Services.Data.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using CareHomeForms.Services.Data.Models.DocumentModels;
    
    namespace CareHomeForms.Models
    {
    	public class EditDocumentViewModel
    	{
    		public Document Document { get; set; }
    		public bool IsUpdate { get; set; }
    		public string ReturnUrl { get; set; }
    		public string PersonId { get; set; }
    	
    	}
    }

    for some reason, all works fine with document but not with incident, but both are the same.

    Friday, September 20, 2019 3:31 PM
  • User197322208 posted

    Please post again the View and the Code that is having error.

    Tuesday, September 24, 2019 3:56 PM
  • User1120430333 posted

    I did what was in the link and made a couple of adjustments in code below.

    https://www.code-sample.com/2014/08/base-controller-in-mvc-5.html

    using System;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    using log4net;
    
    namespace MVC.Controllers
    {
        public abstract partial class BaseController : Controller
        {
            private ILog _logger;
    
            protected BaseController()
            {
                _logger =  LogManager.GetLogger(typeof(BaseController));
            }
    
            protected override void OnException(ExceptionContext filterContext)
            {
                AppException appException = new AppException(Convert.ToString(filterContext.Exception))
                {
                    Type = filterContext.GetType().ToString(),
                    StackTrace = filterContext.Exception.StackTrace,
                    Source = filterContext.Exception.Source,
                    InnerException = Convert.ToString(filterContext.Exception.InnerException)
                };
    
                _logger.Error(appException.ToString());
    
                Server.ClearError();
    
                RedirectToControllers("Home", "Error");
            }
    
            private void RedirectToControllers(string control, string action)
            {
                var routeData = new RouteData();
    
                routeData.Values["controller"] = control;
    
                routeData.Values["action"] = action;
    
                IController controller = new HomeController();
    
                ((IController) controller).Execute(new RequestContext(
                    new HttpContextWrapper(System.Web.HttpContext.Current), routeData));
            }
        }
    }

    Tuesday, September 24, 2019 8:15 PM
  • User627490255 posted
    Turns out the problem was related to the 'internal' statement on the id in the view model.

    Thanks chaps for the help
    Steve
    Tuesday, September 24, 2019 9:46 PM