3

I'm going to create profile for my users in ASP.Net MVC application. Users creation controller is something like this:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserProfileViewModel userViewModel)
{
    if (ModelState.IsValid)
    {
        ....
    }

    return View(userViewModel);
}

Besides, each user model got several properties including one photo. Everything goes well till I want to add an input field to accept photo.

@Html.TextBoxFor(model => model.ImageUrl, new { type = "file" })

And I add below field to UserProfileViewModel:

[Display(Name = "Profile Photo")]
public HttpPostedFileBase ImageUrl { get; set; }

Among snippets to upload a photo and answers to my previous question, it seems uploading photo was considered as a separate task. i.e. I need an individual form and controller to upload a photo (like first part of this answer).

I want to know are there any methods that I can create whole user profile in one form and pass its photo to the same controller (which included photo in UserProfileViewModel)?

I need to note I don't know to use jQuery or AJAX and I want to use standard HTML helpers for this task.

Update: My View Looks like this:

@model ProjectManager.Models.UserProfileViewModel 

@{
    ViewBag.Title = "Create";
}

<h2>@ViewBag.Title</h2>


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

    <div class="form-horizontal">
        <h4>User Profile</h4>
        <hr />
        @Html.ValidationSummary(true)

        <div class="form-group">
            @Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Description)
                @Html.ValidationMessageFor(model => model.Description)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name)
                @Html.ValidationMessageFor(model => model.Name)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Age, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Age)
                @Html.ValidationMessageFor(model => model.Age)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ImageUrl, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.ImageUrl, new { type = "file" })
                @Html.ValidationMessageFor(model => model.ImageUrl)
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="ثبت" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div class="rtl text-right">
    @Html.ActionLink("Back To List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
Community
  • 1
  • 1
VSB
  • 9,825
  • 16
  • 72
  • 145
  • how your view part looks like – Ehsan Sajjad May 09 '16 at 10:28
  • So what problems are you having? –  May 09 '16 at 10:29
  • @StephenMuecke currently file is not posted to ViewModel and ImageURL is null on httppost. – VSB May 09 '16 at 10:40
  • Then show your view - have you includedthe `enctype` attribute in the `
    ` tag?
    –  May 09 '16 at 10:41
  • @StephenMuecke I updated my answer – VSB May 09 '16 at 11:26
  • @EhsanSajjad I added view part – VSB May 09 '16 at 11:26
  • 1
    You need to use an overload of `BeginForm()` that allows you to add htmlAttributes, and because you need to add `new {enctype = "multipart/form-data" }` if you want to upload files. - e.g. `@using (Html.BeginForm("UserProfileViewModel ", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))` –  May 09 '16 at 11:31
  • @StephenMuecke I've tried this already, but my mistake was to write it as `Html.BeginForm("Create", "UserController", FormMethod.Post, new { enctype = "multipart/form-data" }` and I faced with `HTTP Not Found` error. The porblem was about `UserController` which must be `User` and I should not include controller based on conventions. – VSB May 09 '16 at 11:47
  • @StephenMuecke please post your comment as an answer. – VSB May 09 '16 at 11:48

3 Answers3

1

All i have got, your question is I want to know are there any methods that I can create whole user profile in one form and pass its photo to the same controller (which included photo in UserProfileViewModel)?

Yes. It is possible. If you overwrite the form as Stephen Muecke said, you should get the photo with viewmodel. If you get null in viewmodel, you can retrieve the file(photo) from the request also.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserProfileViewModel userViewModel)
  {
    if (ModelState.IsValid)
    {
      HttpPostedFileBase fileUploadObj= Request.Files[0];
      //for collection
      HttpFileCollectionBase fileUploadObj= Request.Files;
    ....
   }

   return View(userViewModel);
  }

Hope this helps :)

Mahbubur Rahman
  • 4,961
  • 2
  • 39
  • 46
  • OP already has a property in the model for the file! - this has nothing to do with the issue. –  May 09 '16 at 11:45
1

File inputs are not sent in the request unless your form element contains the enctype = "multipart/form-data" attribute. Change the view code to

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

You need to use an BeginForm() that allows you to add htmlAttributes, and because you need to add new {enctype = "multipart/form-data" }

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

Controller

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UserProfileViewModel(UserProfileViewModel userViewModel)
{
if (ModelState.IsValid)
{
  HttpPostedFileBase fileUpload= Request.Files[0];
  //for collection
  HttpFileCollectionBase fileUpload= Request.Files;
 ....
 }
Banwari Yadav
  • 506
  • 1
  • 3
  • 18