MVC文件上传器返回null

时间:2012-09-13 15:41:35

标签: asp.net-mvc

我的解决方案基于这篇文章; http://dotnetslackers.com/articles/aspnet/ASP-NET-MVC-and-File-Uploads.aspx

然而,当我尝试上传图片时,我得到的是null而不是文件名。

我的观点看起来像这样;

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SHP.Models.HrViewModel>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit Employee
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <fieldset>
    <legend>Add details to the selected employee</legend>
    <p>The photo you select for an employee will appear on MNet.</p>
    <p>The qualifications you add for an employee will appear on their business cards when required.</p>
        <% using (Html.BeginForm("EditEmployee", "HumanResources", FormMethod.Post,
         new{enctype = "multipart/form-data"}))
           {%>
        <%: Html.AntiForgeryToken() %>
        <%: Html.ValidationSummary(true) %>
        <%: Html.EditorFor(model => model.EmployeeSelector) %>
        <% if (Model.SelectedEmployee != null)
           { %>
                <%: Html.HiddenFor(model => model.SelectedEmployee.EmployeeId) %>
                <%: Html.HiddenFor(model => model.EmployeeName) %>
                <table class="groupBorder" style="margin-top:15px; width:617px;">
                <tbody>
                <tr>
                    <th colspan="2">Add Details for <%: Model.EmployeeName %></th>
                </tr>
                <tr>
                    <td style="text-align: right;">
                <%: Html.LabelFor(model => model.SelectedEmployee.Photo)%>
                   </td>                    
                    <td>
                        <input type="file" id="Picture" name="Picture" />
                    </td>
                </tr>
                <tr>
                    <td style="text-align: right;">
                <%: Html.LabelFor(model => model.SelectedEmployee.Qualifications)%>
                   </td>                    
                    <td>
                <%: Html.TextBoxFor(model => model.SelectedEmployee.Qualifications, new {style = "width:500px;"})%>
                    </td>
                </tr>
                <tr>
                    <td colspan="2" style="text-align: center;padding-top:20px;">
                    <input type="submit" value="Save" id="btnSubmit" /></td>
                </tr>
                </table>
       <% } %>
        <% } %>
        </fieldset>
</asp:Content>

当您单击“保存”按钮时,您将转到此控制器操作;

    [HttpPost]
    [Authorize(Roles = "Administrator, HumanResources, ManagerAccounts, ManagerIT")]
    [ValidateAntiForgeryToken]
    [ValidateOnlyIncomingValues]
    public ActionResult EditEmployee(HrViewModel hrvm)
    {
        if (ModelState.IsValid)
        {
            if (hrvm.SelectedEmployee == null
                || hrvm.EmployeeSelector.SearchTextId != hrvm.SelectedEmployee.EmployeeId)
            {
                return this.RedirectToAction(
                    "EditEmployee", new { employeeId = hrvm.EmployeeSelector.SearchTextId });
            }

            if (hrvm.SelectedEmployee.Picture.HasFile())
            {
                var destinationFolder = Server.MapPath("/Users");
                var postedFile = hrvm.SelectedEmployee.Picture;
                var fileName = Path.GetFileName(postedFile.FileName);
                var path = Path.Combine(destinationFolder, fileName);
                postedFile.SaveAs(path);
                hrvm.SelectedEmployee.Photo = path;
            }   

            var emp = Employee.GetEmployee(hrvm.SelectedEmployee.EmployeeId);
            this.TryUpdateModel<IEmployeeHrBindable>(emp, "SelectedEmployee");
            emp.Update();
            this.TempData["Message"] = string.Format(
                "At {0} Details updated for {1}", DateTime.Now.ToString("T"), hrvm.EmployeeName);
            return this.View(hrvm);
        }

        return this.View(new HrViewModel());
    }

那么我做错了什么?

2 个答案:

答案 0 :(得分:1)

默认情况下,MVC3根据视图中输入元素的Name属性执行模型绑定。

要获取文件上传数据,请使用HttpPostedFileBase类作为ActionResult的参数,并调用参数'file'。

[HttpPost]
[Authorize(Roles = "Administrator, HumanResources, ManagerAccounts, ManagerIT")]
[ValidateAntiForgeryToken]
[ValidateOnlyIncomingValues]
public ActionResult EditEmployee(HrViewModel hrvm, HttpPostedFileBase file)
{
    if (ModelState.IsValid)
    {
        if (hrvm.SelectedEmployee == null
            || hrvm.EmployeeSelector.SearchTextId != hrvm.SelectedEmployee.EmployeeId)
        {
            return this.RedirectToAction(
                "EditEmployee", new { employeeId = hrvm.EmployeeSelector.SearchTextId });
        }
        if (file.ContentLength > 0)
        {
            hrvm.SelectedEmployee.Picture = file;
            var destinationFolder = Server.MapPath("/Users");
            var postedFile = hrvm.SelectedEmployee.Picture;
            var fileName = Path.GetFileName(postedFile.FileName);
            var path = Path.Combine(destinationFolder, fileName);
            postedFile.SaveAs(path);
            hrvm.SelectedEmployee.Photo = path;
        }   

        var emp = Employee.GetEmployee(hrvm.SelectedEmployee.EmployeeId);
        this.TryUpdateModel<IEmployeeHrBindable>(emp, "SelectedEmployee");
        emp.Update();
        this.TempData["Message"] = string.Format(
            "At {0} Details updated for {1}", DateTime.Now.ToString("T"), hrvm.EmployeeName);
        return this.View(hrvm);
    }

    return this.View(new HrViewModel());
}

(所以如果你可以使用模型绑定来获取图像数据,那么它将位于hrvm.Picture而不是hrvm.SelectedEmployee.Picture)

答案 1 :(得分:1)

在您的视图中使用以下代码,默认模型绑定应该起作用:

<%: Html.TextBoxFor(model => model.SelectedEmployee.Photo, new { type = "file" }) %>

假设SelectedEmployee.Photo的类型为HttpPostedFileBase

目前不工作的原因是默认模型绑定器将尝试直接在模型上查找名为Picture的属性,因为这是文件输入的名称。它找不到它,因为Picture是SelectedEmployee的属性。

将其更改为我上面建议的内容会在标记中为文件输入生成正确的ID和名称,因此当回发时具有正确的路径。这意味着默认模型绑定器可以在表单post值和属性之间进行映射。