【问题标题】:Submitting two HTML forms with one submit button in Razor在 Razor 中使用一个提交按钮提交两个 HTML 表单
【发布时间】:2017-01-21 04:34:56
【问题描述】:

首先对不起我的英语不好。我是 ASP.NET MVC 的新手,目前我正在做小型“租车”项目。

我想制作一个表单,页面管理员可以在页面上添加带有 nameyear of productionpicture 等详细信息的汽车。按照一些教程,我制作了一个表格来创建带有名称和生产年份的汽车,然后我单独制作了一个表格,管理员可以上传汽车的图片。

现在我有两个带有两个提交按钮的 HTML 表单,一个用于创建汽车,第二个用于上传汽车图像。我想将这两种形式合并为一个,管理员可以输入汽车名称、生产年份、选择他要上传的图片,然后一键提交所有这些。

我不知道该怎么做,所以请查看下面的代码并告诉我必须进行哪些更改,我将不胜感激

这是我的汽车模型:

public class Car
{
    [Key]
    public int CarID { get; set; }
    public string Model { get; set; }
    public int YearOfProduction { get; set; }
    public string Price { get; set; }
    public string Photo { get; set; }
    public string AlternateText { get; set; }
    [NotMapped]
    public HttpPostedFileBase File { get; set; } //for image upload
}

这是我在“汽车”控制器中的创建(汽车)操作方法:

[Authorize(Roles = "Administrator")]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "CarID,Model,YearOfProduction")] Car car)
    {
        if (ModelState.IsValid)
        {
            db.Cars.Add(car);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(car);
    }

这是我在“汽车”控制器中的上传(汽车图像)操作方法:

    [HttpPost]
    public ActionResult Upload(Car picture)
    {
        if (picture.File.ContentLength > 0)
        {
                var fileName = Path.GetFileName(picture.File.FileName);
                var path = Path.Combine(Server.MapPath("~/Images/Cars"), fileName);
                picture.File.SaveAs(path);
        }

        return RedirectToAction("Index");
    }

这是我用于创建汽车的 HTML 表单:

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

<div class="form-horizontal">
    <h4>Car</h4>
    <hr/>
    @Html.ValidationSummary(true, "", new {@class = "text-danger"})
    <div class="form-group">
        @Html.LabelFor(model => model.Model, htmlAttributes: new {@class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(model => model.Model, new {htmlAttributes = new {@class = "form-control"}})
            @Html.ValidationMessageFor(model => model.Model, "", new {@class = "text-danger"})
        </div>
    </div>

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

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

这是我用于上传汽车图像的 HTML 表单:

@using (Html.BeginForm("Upload", "Cars", FormMethod.Post, new { enctype  = "multipart/form-data" }))
{
<table>
    <tr>
        <td>File:</td>
        <td><input type="file" name="File" id="File"/></td>
    </tr>

        <tr>
            <td>&nbsp;</td>
            <td><input type="submit" name="submit" value="Upload"/></td>
        </tr>
</table>
    }

【问题讨论】:

  • 请缩小代码范围,更好地解释问题所在,等等。

标签: c# html asp.net-mvc forms razor


【解决方案1】:

您可以在&lt;input&gt; 标签中使用命令名称,如下所示:

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

  <!-- Your Razor code for the input form goes here  -->

  <!-- Now your Upload button -->
  <table>
    <tr>
        <td>File:</td>
        <td><input type="file" name="File" id="File"/></td>
    </tr>

        <tr>
            <td>&nbsp;</td>
            <td><input type="submit" name="commandName" value="Upload"/></td>
        </tr>
  </table>

  <!-- Finally, your form submit button -->
   <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" name="commandName" value="Create" class="btn btn-default"/>
        </div>
   </div>

}

并且在您的控制器的操作方法中接受它作为参数。

public ActionResult Create(Car car, string commandName)
{
    if(commandName.Equals("Create"))
    {
      // Call method to create new record...
    }
    else if (commandName.Equals("Upload"))
    {
      // Call another method to upload picture..
    }
}

如果你研究一下,还有另一种优雅的通用解决方案,你可以在 Action 方法上应用一个多按钮属性,它会自动调用控制器动作。但是,您需要小心在这种情况下获取值(*它超出了这个问题的范围)。可以参考:How do you handle multiple submit buttons in ASP.NET MVC Framework?

【讨论】:

    【解决方案2】:

    您可以在其他表单中添加输入文件字段,并将两个操作方法的代码合并为一个。

    @using (Html.BeginForm()) 
    {
      @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Car</h4>
        <hr/>
        @Html.ValidationSummary(true, "", new {@class = "text-danger"})
        <div class="form-group">
            @Html.LabelFor(model => model.Model, htmlAttributes: new {@class = "control-label col-md-2"})
            <div class="col-md-10">
                @Html.EditorFor(model => model.Model, new {htmlAttributes = new {@class = "form-control"}})
                @Html.ValidationMessageFor(model => model.Model, "", new {@class = "text-danger"})
            </div>
        </div>
    
        <div class="form-group">
            @Html.LabelFor(model => model.YearOfProduction, htmlAttributes: new {@class = "control-label col-md-2"})
            <div class="col-md-10">
                @Html.EditorFor(model => model.YearOfProduction, new {htmlAttributes = new {@class = "form-control"}})
                @Html.ValidationMessageFor(model => model.YearOfProduction, "", new {@class = "text-danger"})
            </div>
        </div>
        <div>
          <label>File</label> 
          <input type="file" name="File" id="File"/>
    
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default"/>
            </div>
        </div>
    </div>     
    }
    

    和操作方法,将文件保存到磁盘并将文件名存储在您的数据库表记录中,以便您以后可以检索此文件(用于查看目的)。

    [Authorize(Roles = "Administrator")]
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Car car)
    {
        if (ModelState.IsValid)
        {
          if (car.File.ContentLength > 0)
          {
             var fileName = Path.GetFileName(car.File.FileName);
             var path = Path.Combine(Server.MapPath("~/Images/Cars"), fileName);
             picture.File.SaveAs(path);
             car.Photo = fileName;
          }
          db.Cars.Add(car);
          db.SaveChanges();
          return RedirectToAction("Index");
        }
        return View(car);
    }
    

    另外,您可以考虑生成一个唯一的文件名,这样当用户为不同的记录更新同名文件时,您不会覆盖磁盘上的现有文件。

    您可以使用此代码生成随机文件名。

    var fileName = Path.GetFileName(car.File.FileName);
    fileName = Path.GetFileNameWithoutExtension(fileName) +
                                "_" +
                       Guid.NewGuid().ToString().Substring(0, 4) + Path.GetExtension(fileName);
    var path = Path.Combine(Server.MapPath("~/Images/Cars"), fileName);
    //continue with saving
    

    还请记住,the best way to prevent over posting is by using a view model 具有您的视图所需的属性。您可以创建视图模型并使用它将数据从视图传输到操作方法。在这种情况下,您可以完全删除该属性(用您的实体类中的[NotMapped] 装饰)

    【讨论】:

      【解决方案3】:

      看看this

      看起来它可以帮助您将两个表单(和控制器操作)合并为一个

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-18
        • 1970-01-01
        • 2014-10-08
        • 2020-11-20
        • 2013-03-20
        • 1970-01-01
        • 1970-01-01
        • 2012-01-23
        相关资源
        最近更新 更多