【问题标题】:ASP.NET MVC Route Parameter replacing Model FieldASP.NET MVC 路由参数替换模型字段
【发布时间】:2018-06-04 03:42:14
【问题描述】:

我正在使用 Visual Studio 2017 社区版测试 ASP.NET MVC 5 应用程序。

我正在尝试使用以下代码将Assort 模型保存到数据库。 我正在导航到带有 URL /Assort/Create/1AAssort Create 页面。 在Assortcreate 页面上需要参数1A,因为我需要在创建页面本身上显示该参数的一些附加信息。

但是当我提交数据时,1A 参数值被插入为Assort 模型的ID 值,因此我的ModelState 无效,我无法保存数据。

谁能帮帮我?

型号

public class Assort
{
    [Key]
    public int ID { get; set; }

    [Display(Name = "Assort No")]
    [Required(ErrorMessage = "Assort No can not be empty.")]
    public int ASSORTNO { get; set; }

    [Display(Name = "Date")]
    [Required(ErrorMessage = "Date can not be empty.")]
    public DateTime DATE { get; set; }

    [Display(Name = "RFNO")]
    [Required(ErrorMessage = "RFNO can not be empty.")]
    [StringLength(50)]
    public string RFNO { get; set; }

    [Display(Name = "Manager")]
    [Required(ErrorMessage = "Manager can not be empty.")]
    public int MANAGER { get; set; }

    [Display(Name = "Caret")]
    [Required(ErrorMessage = "Caret can not be empty.")]
    public decimal CARET { get; set; }

    [Display(Name = "MFG Size")]
    [Required(ErrorMessage = "MFG Size can not be empty.")]
    public decimal MFGSIZE { get; set; }

    [Display(Name = "Total PCS")]
    [Required(ErrorMessage = "Total PCS can not be empty.")]
    public decimal TOTALPCS { get; set; }

    [StringLength(50)]
    public string APPROVALSTATUS { get; set; }

    [Display(Name = "Details")]
    public string DETAILS { get; set; }

    [ScaffoldColumn(false)]
    public DateTime CREATE_TIMESTAMP { get; set; }
    [ScaffoldColumn(false)]
    public DateTime LAST_EDIT_TIMESTAMP { get; set; }

    [UIHint("AssortReturn")]
    public virtual List<AssortReturn> AssortReturn { get; set; }

    public Assort()
    {
        AssortReturn = new List<AssortReturnModel.AssortReturn>();
    }

    [ForeignKey("RFNO")]
    public virtual Rough rough { get; set; }
}

动作

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Assort assort)
    {
        if (ModelState.IsValid)
        {
            assort.APPROVALSTATUS = "NOT APPROVED";
            assort.CREATE_TIMESTAMP = DateTime.Now;
            assort.LAST_EDIT_TIMESTAMP = DateTime.Now;
            db.Assorts.Add(assort);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        Initialize(assort.RFNO,"CREATE");
        return View(assort);
    }

查看

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

<div class="form-horizontal">

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

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

    <div class="form-group">
        @Html.LabelFor(model => model.RFNO, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.RFNO, new { htmlAttributes = new { @readonly = "readonly", @Value = ViewBag.RFNO, @class = "form-control" } })
            @Html.TextBox("AVAILABLECARET",(decimal)ViewBag.AVAILABLECARET,new {@class="form-control txtAvailablecaret",@readonly="readonly" })
            @Html.ValidationMessageFor(model => model.RFNO, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.MANAGER, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @*@Html.EditorFor(model => model.MANAGER, new { htmlAttributes = new { @class = "form-control" } })*@
            @Html.DropDownListFor(model => model.MANAGER, new SelectList(ViewBag.MANAGERLIST, "ID", "USERNAME"), "Select Manager", new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.MANAGER, "", new { @class = "text-danger" })
        </div>
    </div>

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

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

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

    <div class="form-group">
        @Html.LabelFor(model => model.DETAILS, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.DETAILS, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.DETAILS, "", 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 btnCreate" />
        </div>
    </div>
</div>

}

【问题讨论】:

  • 为什么不发送“1A”作为ID以外的参数?喜欢create?param1=1A
  • @sachin 如果我想保持干净的 URL 怎么办?还有其他建议吗?
  • 所以你想要A1,但是作为不同参数的值,没有ID?
  • @Andrei,是的,我想要那个。
  • 您正在编辑数据,因此您应该始终使用视图模型,并且该视图模型可以包含一个属性(例如)public int AssortID { get; set; },因此它不会自动与路由值绑定。

标签: asp.net-mvc routes modelstate


【解决方案1】:

这是因为处理您的请求的默认路由。它看起来像:

{controller}/{action}/{id}

因此 A1 绑定到 ID。如果你想要不同的行为,比如 A1 仍然是 URL 的一部分,但绑定到不同的参数,比如“名称”,你需要一个新的路由:

    routes.MapRoute(
        name: "CreateAssort",
        url: "Assort/Create/{name}",
        defaults: new { controller = "Assort", action = "Create"}
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

现在“名称”将包含 A1 而不是 ID。请注意您的自定义路由是如何出现在默认路由之前的。这很重要 - 路由选择与请求匹配的第一个路由。

【讨论】:

  • 正如您所建议的,路由选择与请求匹配的第一个路由。但是Assort/Create/1A 应该匹配两条路线。我错了吗?
  • 为什么id不能保存1A的值?
  • 另外,如果我也需要对其他路线做同样的事情,我的 routeconfig 文件将充满不适合的路线。
  • @Hemal,是的,它匹配两条路线,这并不罕见,这就是为什么存在关于选择第一个匹配项的规则的原因。 id 绝对可以保存 A1 的值,但是您的帖子听起来好像这不是您想要的。如果您想要其他路线,您可以随时概括路线,如果相当具体,我发布的内容。如果您愿意,您甚至可以生成它们
【解决方案2】:

您可以在视图中添加一个名为IDhidden 输入字段。

提交表单时,此字段中的值将优先于您路线中的值,即“1A”,如果您不设置隐藏输入的值,模型的 ID 将为 0。

【讨论】:

  • 我将无法在隐藏字段中保存该值。 Assort/Create/1A url 是从网格中可用的超链接触发的。并且有很多类似的记录。所以这个 url 是从一个超链接触发的。
  • @Hemal 我说的是在表单所在的视图中添加一个隐藏字段。您只需添加“&lt;input type="hidden" name="ID" /&gt;”即可
【解决方案3】:

我有同样的问题。但问题在于创建模型时。

你需要有两种方法。

[HttpGet] // http://localhost/Assort/Create/1
public ActionResult Create(int Id)
{
   ModelState.Remove(nameof(Id)); // this will remove binding
   var assort = new Assort()
   {
    Id = 'whatever',
   ....
   };
   
   return View(assort);
}

[HttpPost] // http://localhost/Assort/Create/
public ActionResult Create(Models.Assort assort)
{
   if (ModelState.IsValid)
    {
        assort.APPROVALSTATUS = "NOT APPROVED";
        assort.CREATE_TIMESTAMP = DateTime.Now;
        assort.LAST_EDIT_TIMESTAMP = DateTime.Now;
        db.Assorts.Add(assort);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    Initialize(assort.RFNO,"CREATE");
    return View(assort);
}

C# ASP MVC Route Model ID bug

【讨论】:

    猜你喜欢
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多