0

I have a controller in which I have Create method .My aim is to upload picture along with name and service involved for a particular person.My code is perfectly good.But I'm hitting the error 'Object reference not set to the instance of an object' at the line 'if (leader.File.ContentLength > (2 * 1024 * 1024))' in controller.The code is perfectly good.Please let me know where I'm doing mistake

I have model class like this:

   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int ID { get; set; }

   [Required(ErrorMessage="The Name is required")] 
   [MaxLength(20,ErrorMessage="The Maximum characters allowed is 20")]
   [MinLength(4,ErrorMessage="The Minimum charcaters allowed is 4")]
   public string Name { get; set; }

   [Required(ErrorMessage="Picture is required")]
   public byte[] Picture { get; set; }

   public int ImageSize { get; set; }

   [NotMapped]
   public HttpPostedFileBase File { get; set; }

   public int MinistryID { get; set; }

   [ForeignKey("MinistryID")]
   public virtual Ministry Ministry { get; set; }

I have Controller class with create method like this:

   public ActionResult Create()
        {

            return View();
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(Leader leader)
        {
            if (leader.File.ContentLength > (2 * 1024 * 1024))
            {
                ModelState.AddModelError("CustomError", "File size must be
             less than 2 MB");
                return View();
            }
            if (!(leader.File.ContentType == "image/jpeg" || 
           leader.File.ContentType == "image/gif"))
            {
                ModelState.AddModelError("CustomError", "File type allowed :
              jpeg and gif");
                return View();
            }

            leader.ImageSize = leader.File.ContentLength;

            byte[] data = new byte[leader.File.ContentLength];
            leader.File.InputStream.Read(data, 0,
            leader.File.ContentLength);

            leader.Picture = data;
           if(ModelState.IsValid)
            {
                db.Leaders.Add(leader);
                db.SaveChanges();
            }
            return View(leader);

        }
        }

The View of the Create method is :

     @model ChurchWebsite.Models.Leader

@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Leader</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div>
            @Html.LabelFor(model=>model.Picture)
        </div>
         <div>
        @using (Html.BeginForm("Upload","Image", FormMethod.Post,new{enctype="multipart/form-data"}))
            {
            @Html.TextBoxFor(Model=> Model.File, new{type="file",enctype="multipart/form-data"})
            @Html.ValidationMessage("CustomError")
           </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.MinistryID)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.MinistryID)
            @Html.ValidationMessageFor(model => model.MinistryID)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}



@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
sujay raj
  • 89
  • 11
  • 1
    _My code is perfectly good_ No it not! Because `File` is `null` (you don't have a form control for uploading a file) –  Oct 30 '15 at 02:45
  • Possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) –  Oct 30 '15 at 02:46
  • And the model in the view is typeof `Ministry` but the POST method you have shown bind to typeof `Leader` You have not even shown the right code! –  Oct 30 '15 at 02:50
  • @StephenMuecke, I have Html.BeginForm at the beginning of view .Should I include it again near the Upload of file – sujay raj Oct 30 '15 at 03:52
  • @sujayraj No. See: [Is it valid to have a html form inside another html form?](http://stackoverflow.com/questions/555928/is-it-valid-to-have-a-html-form-inside-another-html-form) – Mike Oct 30 '15 at 03:54
  • 1
    You cannot have nested forms. Remove the inner form. Add `new { enctype="multipart/form-data" }` to the outer form and remove `enctype="multipart/form-data"` from the file input (and don't use capital `M` Model in expressions). –  Oct 30 '15 at 03:57
  • @StephenMuecke nailed it. As an aside, note that one solid troubleshooting method is to strip your MVC flow down to a simple, working process, [like the one shown here](http://stackoverflow.com/a/19186560/772086), and then iteratively build it out to match your intended model. – Mike Oct 30 '15 at 04:03

1 Answers1

1

You have nested forms which is invalid html and when you click the submit button in the inner form, it will post the outer form which does not have the enctype="multipart/form-data" attribute and as a consequence, the file is not sent and in the controller, leader.File is null and accessing its ContentLength property throws the exception. You need to remove the inner nested form element and add the enctype attribute to the outer form.

Your view should be (irrelevant html removed)

@model ChurchWebsite.Models.Leader
....
@using (Html.BeginForm("Create", YourControllerName, FormMethod.Post, new{ enctype="multipart/form-data" })) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    ....
    @Html.LabelFor(m => m.Name)
    @Html.EditorFor(m => m.Name)
    @Html.ValidationMessageFor(m => m.Name)
    ....
    @Html.TextBoxFor(m => m.File, new{ type="file" }) // remove the inva;id enctype attribute
    @Html.ValidationMessage("CustomError")
    ....
    @Html.LabelFor(model => model.MinistryID)
    @Html.EditorFor(model => model.MinistryID)
    @Html.ValidationMessageFor(model => model.MinistryID)
    <input type="submit" value="Create" />
}
  • Sorry Stephen, I tried your code.I'm not getting any error.But I see that the data is not stored in the database – sujay raj Oct 30 '15 at 04:55
  • Has the exception gone? –  Oct 30 '15 at 05:00
  • Yep..It's gone..@Stephen – sujay raj Oct 30 '15 at 05:00
  • Then you question has been answered :). If you have another problem then ask a new question. –  Oct 30 '15 at 05:01
  • It's working when I removed the code 'if(ModelState.IsValid)' in the Action Method.Thanks a ton – sujay raj Oct 30 '15 at 05:02
  • That's because you have a `[Required]` attribute on the `Picture` so when you submit the form, the `DefaultModelBinder` added a `ModelState` error because `Picture` was null. You should remove it so you can still test if its valid. –  Oct 30 '15 at 05:05