user508945
user508945

Reputation: 83

Attachment with Postal MVC don't work

I have a MVC3 project. In my contact page I would like to add the possibility of adding an attachment to Email sent by customer.

I am using Postal. It works well but I can't get the attachment working.

Here is the part of my code dealing with this:

I have a model class:

public class ContactEmail
{
    [ScaffoldColumn(false)]
    public int id { get; set; }

    [Required(ErrorMessage = "Name is required!")]
    [DataType(DataType.Text)]
    [DisplayName("Name")]
    public string name { get; set; }

    [Required(ErrorMessage = "Email Address is required!")]
    [DataType(DataType.EmailAddress)]
    [DisplayName("Email Address")]
    [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "Email Address is not valid.")]
    public string email { get; set; }

    [Required(ErrorMessage = "Country is required!")]
    [DisplayName("Country")]
    public string country { get; set; }

    [DisplayName("Subject")]
    public string subject { get; set; }

    [Required(ErrorMessage = "Message is required!")]
    [DisplayName("Message")]
    [StringLength(1500)]
    public string message { get; set; }

    [ScaffoldColumn(false)]
    public DateTime datetime { get; set; }

    public HttpPostedFileBase attachment { get; set; }

Here is my Postal Controller:

public class PostalController : Controller
{
    [HttpPost]
    public ActionResult Send(ContactEmail model)
    {

        if (ModelState.IsValid)
        {
            Random random = new Random();
            var ticket = random.Next(1000000000, 2000000000);

            dynamic courriel = new Email("Postal");
            courriel.To = "[email protected]";
            courriel.Name = model.name;
            courriel.Country = model.country;
            courriel.Subject = model.subject;
            courriel.From = model.email;
            courriel.Message = model.message;
            courriel.TicketId = ticket;
            courriel.Attachment = model.attachment;
            //if (model.Attachment != null && model.Attachment.ContentLength > 0)
            //{
            //    var attachment = new Attachment(model.Attachment.InputStream, model.Attachment.FileName);
            //    courriel.Attachments.Add(attachment);
            //}
            //courriel.Attachment = model.Attachment; 

            courriel.Attach(new Attachment(model.attachment.InputStream, model.attachment.FileName));

            Task task = courriel.SendAsync();

            //courriel.Send();

            return RedirectToAction("Sent", "Contact");
        }

        ViewData["MessageSent"] = false;

        return View("~/Views/Contact/Contact.cshtml");
    }

and finally here is the form I use in my Contact.cshtml view:

@using (Html.BeginForm("Send", "Postal"))
{        
    @Html.ValidationSummary(false)

    <p>
       @Html.LabelFor(model => model.name)
       @Html.TextBoxFor(model => model.name, new { @size = 35 })
       @Html.ValidationMessageFor(model => model.name, "*")
    </p>                      
    <p>
       @Html.LabelFor(model => model.email)
       @Html.TextBoxFor(model => model.email, new { @size = 35 })
       @Html.ValidationMessageFor(model => model.email, "*")
    </p>
    <p>
       @Html.LabelFor(model => model.subject)
       @Html.DropDownList(
           "subject", 
           new[] { 
               new SelectListItem { 
                   Text = "NT Indicator Quote", 
                   Value = "NT Indicator Quote" 
               }, 
               new SelectListItem { 
                   Text = "NT Strategy Quote", 
                   Value = "NT Strategy Quote" 
               }, 
               new SelectListItem { 
                   Text = "Comments", 
                   Value = "Comments" 
               }, 
               new SelectListItem { 
                   Text = "other", 
                   Value = "other" 
               }
           }
       ); // @Html.DropDownList(
       @Html.ValidationMessageFor(model => model.subject, "*")
    </p>
    <p>
       @Html.LabelFor(model => model.message)
       @Html.TextAreaFor(model => model.message, new { @cols = 50, @rows = 10 })
       @Html.ValidationMessageFor(model => model.message, "*")
    </p>
    <p>
       @Html.LabelFor(model => model.attachment)
       @Html.TextBoxFor(model => model.attachment, new { type = "file" })
       @Html.ValidationMessageFor(model => model.attachment)
    </p>          
    <p><input type="submit" id="submit" name="submit" value="Submit" /></p>            
} <!-- End form -->

I get the following error message :

Object reference not set to an instance of an object. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error: Line 44: courriel.Attach(new Attachment(model.attachment.InputStream, model.attachment.FileName));

Could you please help me find out the problem here ? Thank you !

Here is the HTML from the view source :

<form action="/Postal/Send?enctype=multipart%2Fform-data" method="post">
    <div class="validation-summary-valid" data-valmsg-summary="true">
        <ul>
            <li style="display:none"></li>
        </ul>
    </div>
    <p>
        <label for="name">Name</label>
        <input data-val="true" data-val-required="Name is required!" id="name" name="name" size="35" type="text" value="" />
        <span class="field-validation-valid" data-valmsg-for="name" data-valmsg-replace="false">*</span>
    </p>
    <p>
        <label for="email">Email Address</label>
        <input data-val="true" data-val-regex="Email Address is not valid." data-val-regex-pattern="[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}" data-val-required="Email Address is required!" id="email" name="email" size="35" type="text" value="" />
        <span class="field-validation-valid" data-valmsg-for="email" data-valmsg-replace="false">*</span>
    </p>
    <p>
        <label for="subject">Subject</label>
        <select id="subject" name="subject">
            <option value="NT Indicator Quote">NT Indicator Quote</option>
            <option value="NT Strategy Quote">NT Strategy Quote</option>
            <option value="Comments">Comments</option>
            <option value="other">other</option>
        </select>
        <span class="field-validation-valid" data-valmsg-for="subject" data-valmsg-replace="false">*</span>
    </p>
    <p>
        <label for="message">Message</label>
        <textarea cols="50" data-val="true" data-val-length="The field Message must be a string with a maximum length of 1500." data-val-length-max="1500" data-val-required="Message is required!" id="message" name="message" rows="10">
        </textarea>
        <span class="field-validation-valid" data-valmsg-for="message" data-valmsg-replace="false">*</span>
    </p>
    <p>
        <label for="attachment">attachment</label>
        <input id="attachment" name="attachment" type="file" value="" />
        <span class="field-validation-valid" data-valmsg-for="attachment" data-valmsg-replace="true"></span>
    </p>
    <p>
        <input type="submit" id="submit" name="submit" value="Submit" />
    </p>
</form> <!-- End form -->

    </div>

Upvotes: 1

Views: 1896

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

You need to append the enctype="multipart/form-data" attribute to the form if you want to upload files:

@using (Html.BeginForm("Send", "Postal", FormMethod.Post, new { enctype = "multipart/form-data" })) 
{
    ...
}

Also checkout this blog post by the Haacked.

Upvotes: 3

Related Questions