Can EditorFor() be used to create <input type="file">?
Asked Answered
B

4

24

Given this model, is it possible to use the Html.EditorFor() to render a file upload input element to the page? I played around with the Datatype of the property FileName, and it was definitely impacting the editor form rendered.

public class DR405Model
{
    [DataType(DataType.Text)]
    public String TaxPayerId { get; set; }
    [DataType(DataType.Text)]
    public String ReturnYear { get; set; }

    public String  FileName { get; set; }
}

Strongly Typed *.aspx page looks like this

    <div class="editor-field">
        <%: Html.EditorFor(model => model.FileName) %>
        <%: Html.ValidationMessageFor(model => model.FileName) %>
    </div>
Bausch answered 24/5, 2011 at 16:6 Comment(1)
MVC4 - I have been wondering why DataType.Upload doesn't render type="file"Cabman
B
39

It would make more sense to use HttpPostedFileBase to represent an uploaded file on your view model instead of string:

public class DR405Model
{
    [DataType(DataType.Text)]
    public string TaxPayerId { get; set; }

    [DataType(DataType.Text)]
    public string ReturnYear { get; set; }

    public HttpPostedFileBase File { get; set; }
}

then you could have the following view:

<% using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { %>

    ... input fields for other view model properties

    <div class="editor-field">
        <%= Html.EditorFor(model => model.File) %>
        <%= Html.ValidationMessageFor(model => model.File) %>
    </div>

    <input type="submit" value="OK" />
<% } %>

And finally define the corresponding editor template inside ~/Views/Shared/EditorTemplates/HttpPostedFileBase.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<input type="file" name="<%: ViewData.TemplateInfo.GetFullHtmlFieldName("") %>" id="<%: ViewData.TemplateInfo.GetFullHtmlFieldId("") %>" />

Now the controller might look like this:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new DR405Model());
    }

    [HttpPost]
    public ActionResult Index(DR405Model model)
    {
        if (model.File != null && model.File.ContentLength > 0)
        {
            var fileName = Path.GetFileName(model.File.FileName);
            var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
            model.File.SaveAs(path);
        }

        return RedirectToAction("Index");
    }
}
Buckling answered 25/5, 2011 at 6:33 Comment(3)
Thanks that's the answer I was looking for.Bausch
You could also use @Html.TextBoxFor(x => x.File, new { type = "file" })Gamesmanship
@Darin -What will be the type of data if I am saving File url in a Database. In Model you have - "HttpPostedFileBase"Languet
S
10

Here's an example for MVC 5 (required for the htmlAttributes).

Create this as a file called HttpPostedFileBase.cshtml under ~\Views\Shared\EditorTemplates

@model HttpPostedFileBase
@{
    var htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(ViewData["htmlAttributes"]);
    htmlAttributes["type"] = "file";
}
@Html.TextBoxFor(model => model, htmlAttributes)

This generates the control with the correct id and name and works when editing collections from a model EditorFor template.

Sagunto answered 17/11, 2015 at 10:48 Comment(3)
It seems important to note here that there may be more going on behind the scenes.The above would not work until a setting in the .cshtml file's properties got switched: Build Action, None --> Content. Per a response on this question: linkScotland
Couple of points, the build action of .cshtnl is Content by default and the answer you are referring to is from 2011 and talks about MVC 3 - MVC 5 I had to make no changes to make this workSagunto
Works like breeze. No extra change apart from editor template requiredCarmeliacarmelina
P
6

Add: htmlAttributes = new { type = "file" }

<div class="editor-field">
    <%: Html.EditorFor(model => model.FileName, new { htmlAttributes = new { type = "file" }}) %>
    <%: Html.ValidationMessageFor(model => model.FileName) %>
</div>

Note: I'm using MVC 5, I have not tested on other versions.

Palacio answered 30/1, 2017 at 12:59 Comment(0)
L
0

No but take a look at http://haacked.com/archive/2010/07/16/uploading-files-with-aspnetmvc.aspx

Louiselouisette answered 24/5, 2011 at 16:8 Comment(1)
Already built that. Maybe I'm going the wrong direction. I have aspnet_db profile data, that I'll need to marry with the file uploaded. So, that the users file gets saved to the server with user_id + date + "xlsx" I was thinking I needed to create a model, that had properties beyond the file object alone.Bausch

© 2022 - 2024 — McMap. All rights reserved.