20

I have a form where a user can upload a file to the sites download section. However when the form is submitted I get this error, without the request ever making it to the action method.

"The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters."

Code:

[HttpPost]
    [Authorize]
    public ActionResult Create(Download dl, HttpPostedFileBase DownloadFile)
    {

And

@model Models.Download

@{
    ViewBag.Title = "Add Download";
}

<h3>Add Download</h3>

@using (Html.BeginForm("Create", "Download", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.ValidationSummary(true)

    <div class="editor-label">Download File</div>
    <div class="editor-field">
        <input name="DownloadFile" id="DownloadFile" type="file" />
        @Html.ValidationMessage("DownloadFile");
    </div>

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

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

    <div class="display-field"><input type="submit" value="Add" /></div>
}

<div>@Html.ActionLink("Back To Downloads", "Index")</div>

Any sugestions?

Thanks, Alex.

Alex Hope O'Connor
  • 9,354
  • 22
  • 69
  • 112

3 Answers3

30

Ok I figured this out finally, It was all caused because I named the file input on the form the same as my models file field, so the model binder was picking this up and trying to bind the posted file directly to the binary property which was throwing an exception because the string was not binary.

So to fix it I simply added this to my create action method:

[HttpPost]
    [Authorize]
    public ActionResult Create([Bind(Exclude = "DownloadFile")] Download dl, HttpPostedFileBase DownloadFile)
    {

By telling the model binder to exclude the field it solved the problem.

Thanks, Alex.

EDIT: This could also easily be solved by using view models

Alex Hope O'Connor
  • 9,354
  • 22
  • 69
  • 112
  • nice thanks ! do you know why the binder couldn't bind this property? – Ashkan Jan 31 '13 at 22:38
  • Because the field on my model was not of the type HttpPostedFileBase and it was trying to bind directly to the 'Download' model instead of the HttpPostedFileBase parameter 'DownloadFile' – Alex Hope O'Connor Jan 31 '13 at 22:54
  • I understand that, I mean why the binder could not bind the uploaded file directly to `DownloadFile` Property? Is it a lack of functionality or there is a reason not to? – Ashkan Feb 05 '13 at 17:45
  • Because the field on the model was not of the type HttpPostedFileBase, it could also of easily been solved by creating a view model. – Alex Hope O'Connor Feb 05 '13 at 21:35
  • 2
    Of course, I think it would be a good thing if the binder determines the type of property and converts the file to byte array. – Ashkan Feb 05 '13 at 22:53
  • You could implement your own binder that would do this for you if you wanted to. – Alex Hope O'Connor Feb 05 '13 at 23:17
  • 1
    +1 Have you ever had the feeling that you just saved someone's day ? – Yaseen Jul 20 '13 at 06:16
4

Alex, you are partially correct with your assessment. The reason why it fails when you have a property of the same name on your model as the name of the input object on the form is due to the fact that the DataType of the matchingly-named property on your model is not System.Web.HttpPostedFileWrapper which is the datatype that the binary-binder will attempt to perform a bind to.

Excluding your property by using the Bind attribute and then extracting the file from the Request.Files collection as you demonstrated may work, but it may be more elegant to let the binder do its thing (provided that the data type is matching as I mentioned above) and then you can simply access the file directly from the property of your model

Awah Teh
  • 1,217
  • 13
  • 12
  • In this case I was not using view models and was binding directly to database entity models. If I was using view models I would have changed the data type to match the binders data type. – Alex Hope O'Connor Feb 05 '13 at 04:17
1

You could try removing the HttpPostedFileBase from the controller method and use Request.Files[0] and see if that makes a difference.

Honestly though I dont'see why this would be failing unless there is something that is causing it within your Model.

Also, nit picking here but DownloadFile should be downloadFile on your form and in your controller method.

Mike Geise
  • 825
  • 7
  • 15
  • 1
    Lol thank you, solved this literally as you answered, changed the form field name and it worked straight away, which led me to the conclusion that the model binder was doing it. Your nit picking would have solved the issue lol. Thanks. – Alex Hope O'Connor Feb 26 '11 at 07:00