3

I have 2 file upload for editing user profile in partial view that called from user profile page. The problem is HttpPostedFileBase parameter in action method always null.

When I'm calling this partial view out of profile page and without layout, file uploads was successfully done and sent files to action method.

This is my action method in controller:

[AcceptVerbs(HttpVerbs.Post)]
[Authorize(Roles = "User")]
public ActionResult EditProfile(ProfileGeneralDescription editedModel,
                                   HttpPostedFileBase imageFile,
                                   HttpPostedFileBase coverFile)
{
         //Some code here...   
}

And this is my partial view cshtml code:

@model Website.Models.ViewModel.Profile

@using (Ajax.BeginForm("EditProfile", "Profile", new { postOwnerUser = User.Identity.Name }, new AjaxOptions()
{
    HttpMethod = "POST",
    InsertionMode = InsertionMode.Replace,
    UpdateTargetId = "GeneralSection"
}, new { enctype = "multipart/form-data" }))
{

    <div>
        <button type="submit" name="Save" class="btn btn-default btn-xs">Save Changes</button>
        @Ajax.ActionLink("Cancel", "ProfileDescription", "Profile",
            new {username = Model.Username, type = "Show"},
            new AjaxOptions()
            {
                HttpMethod = "GET",
                InsertionMode = InsertionMode.Replace,
                UpdateTargetId = "GeneralSection"
            },
            new {@class = "btn btn-default btn-xs"})
    </div>

    <input type="hidden" name="username" id="username" value="@Model.Username"/>

    <fieldset>
        <legend>Edit Photos</legend>
        <div>
            Select profile picture:
            <input id="imageFile" type="file" name="imageFile" accept="image/png, image/jpeg" />
            @Html.CheckBoxFor(modelItem => modelItem.DefaultCover)<span>Remove profile photo</span>
        </div>
        <div>
            Select cover picture:
            <input id="coverFile" type="file" name="coverFile" accept="image/png, image/jpeg" />
            @Html.CheckBoxFor(modelItem => modelItem.DefaultCover)<span>RemoveCover</span>
        </div>
    </fieldset>
}

Where is my mistake?
Thanks in advance.

8
  • 1
    Do you need the [HttpPost] attribute? Commented Dec 16, 2013 at 11:12
  • I'm forget copy this codes. Please see my update. Commented Dec 16, 2013 at 11:26
  • Can you give code showing how you are calling the partial view when it is not working? Commented Dec 16, 2013 at 11:43
  • This is my action link: @Ajax.ActionLink("Edit Profile", "ProfileGeneralDescription", "Profile", new { username = Model.Username, type = "Edit" }, new AjaxOptions() { HttpMethod = "GET", InsertionMode = InsertionMode.Replace, UpdateTargetId = "GeneralSection" }, new { @class = "btn btn-default btn-xs" } ) Commented Dec 16, 2013 at 11:46
  • I found this post: mvc3 file upload using ajax form - Request.Files empty that best answer said Ajax form doesn't support file upload. What do I do to edit user profile? Commented Dec 16, 2013 at 11:49

1 Answer 1

2

File uploads are normally initiated using a straightforward form post. If you want to initiate an upload using AJAX, you need to write some javascript to use the XmlHttpRequest (XHR) object, something like this (using jQuery):

<script>
    function submit (e){
        e.preventDefault = true;
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(e) {
            if ( 4 == this.readyState ) {
                console.log(['xhr upload complete', e]);
            }
        };
        xhr.open('post', 'Profile/EditProfile', true);
        xhr.setRequestHeader("Content-Type","multipart/form-data");
        var formData = new FormData();
        formData.append("imageFile", $("#imageFile").files[0]);
        formData.append("coverFile", $("#coverFile").files[0]);
        // etc
        xhr.send(formData);
    };
</script>

Note that you populate the javascript FormData object in code using the values from your form elements. Then wire this function to your submit button's click event:

    <button type="button" name="Save" onclick="submit()" class="btn btn-default btn-xs">Save Changes</button>

You can also remove the Ajax form in your view as it won't be needed when using this approach.

Sign up to request clarification or add additional context in comments.

15 Comments

That's nice job! Thanks @Paul :-)
How can I replace returned partial view with this block? (like AjaxOptions in Ajax.BeginForm() ). Current Option in beginForm function doesn't work!
Is any updated data returned by your controller method that needs to be displayed?
If you do, you can get the server response from the XHR object like this: xhr.responseText or xhr.responseXML. Your script will then need to apply it to the relevant html element.
Yes, I do this as you said. But profile page was gone and returned partial view showed in browser. this script don't replace anything and seems it's not working after post data.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.