asp.net mvc 脚手架和 GUID 作为主键

发布于 2024-11-25 10:05:18 字数 2479 浏览 3 评论 0原文

我有一个具有以下结构的表

GUID uniqueidentifier with default value newid(), and set as primary key
ID int
Description varchar(max)

我使用 Visual Studio 创建了一个实体模型,并生成了用于编辑/删除等的视图(MVC 脚手架)

问题在于“编辑”,当我单击该链接时,会显示适当的表单数据正确,但“保存”按钮根本不起作用。请注意,其他链接(删除、创建、详细信息)工作正常。

因此,当我单击“编辑”链接时,网址为

http://localhost:10871/admin/Edit/e7d0c5ee-7782-411f-920e-7b0d93c924e1

表单显示正确,但保存按钮不起作用,没有网络活动发生。使用 uniqueidentifers 作为主键有什么特别之处吗?

谢谢

---代码---

Edit.cshtml

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Domain</legend>

        @Html.HiddenFor(model => model.GUID)

        @Html.HiddenFor(model => model.ID)

        <div class="editor-label">
            @Html.LabelFor(model => model.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Description)
            @Html.ValidationMessageFor(model => model.Description)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

--AdminController.cs--

// GET: /Admin/Edit/5

public ActionResult Edit(Guid id)
{
    Domain domain = db.Domains.Single(d => d.GUID == id);
    return View(domain);
}

//
// POST: /Admin/Edit/5

[HttpPost]
public ActionResult Edit(Domain domain)
{
    if (ModelState.IsValid)
    {
        db.Domains.Attach(domain);
        db.ObjectStateManager.ChangeObjectState(domain, EntityState.Modified);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(domain);
}

Edit2 为了回应 ZippyV 的评论,

<div class="editor-label">
            @Html.LabelFor(model => model.ID)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ID)
            @Html.ValidationMessageFor(model => model.ID)
        </div>

令我惊讶(或无知)的是,我在 Edit.cshtml 中添加了以下代码 - 显示的是 GUID 而不是 ID GUID is shown as ID

除此之外 - 当我在该字段中输入值(1,2 或任何整数)时,我仍然收到消息“字段 ID 必须是数字”。

I have a table with the following structure

GUID uniqueidentifier with default value newid(), and set as primary key
ID int
Description varchar(max)

I created an Entity Model using visual studio, and generated the views for editing/deleting etc (mvc scaffolding)

The problem is with "Editing", when I click that link, the appropriate form is showed with the correct data, but the "save" button doesn't work at all. Please note that other links (delete,create,details) work perfectly..

So, when I click the "Edit" link, the url is

http://localhost:10871/admin/Edit/e7d0c5ee-7782-411f-920e-7b0d93c924e1

and the form is displayed correctly, but the save button doesn't work, no network activity happens. Is something particular about using uniqueidentifers as primary key?

Thanks

---Code---

Edit.cshtml

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Domain</legend>

        @Html.HiddenFor(model => model.GUID)

        @Html.HiddenFor(model => model.ID)

        <div class="editor-label">
            @Html.LabelFor(model => model.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Description)
            @Html.ValidationMessageFor(model => model.Description)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

--AdminController.cs--

// GET: /Admin/Edit/5

public ActionResult Edit(Guid id)
{
    Domain domain = db.Domains.Single(d => d.GUID == id);
    return View(domain);
}

//
// POST: /Admin/Edit/5

[HttpPost]
public ActionResult Edit(Domain domain)
{
    if (ModelState.IsValid)
    {
        db.Domains.Attach(domain);
        db.ObjectStateManager.ChangeObjectState(domain, EntityState.Modified);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(domain);
}

Edit2
In response to a comment by ZippyV, I added the following code in Edit.cshtml

<div class="editor-label">
            @Html.LabelFor(model => model.ID)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ID)
            @Html.ValidationMessageFor(model => model.ID)
        </div>

to my surprise (or ignorance) - the GUID is being shown instead of ID
GUID is shown as ID

and apart from that - when I enter a value in that field (1,2 or any integer), I still get the message "The field ID must be a number."

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

惜醉颜 2024-12-02 10:05:18

问题来自这样一个事实:您的视图模型上有一个名为 ID 的属性:

public class Domain
{
    public int ID { get; set; }
    ...
}

同时您的 Edit 控制器操作中有一个名为 id 的路由参数:

public ActionResult Edit(Guid id)
{
    ...
}

现在发生的事情是这样的:Html 帮助器(例如 TextBoxFor、HiddenFor 等)在绑定值(即查询字符串参数、路由值)时总是首先查看模型状态,并且仅在最后才查看中的值模型。这就是所有 Html 助手的工作方式,也是设计使然。

因此,您有以下内容:

@Html.HiddenFor(model => model.ID)

ID 不是从模型中获取,而是从您的路线数据(这是您的操作参数中指定的 Guid)中获取。这就是为什么在视图模型和操作参数中使用同名的属性是非常危险的。

一种可能的解决方法是将操作参数重命名为其他名称:

public ActionResult Edit(Guid domainId)
{
    Domain domain = db.Domains.Single(d => d.GUID == domainId);
    return View(domain);
}

当然,现在您的路由可能需要调整或使用查询字符串参数:controller/edit?domainId=d578b4b7-48ec-4846-8a49-2120c17b6441 调用编辑操作。

The problem comes from the fact that you have a property called ID on your view model:

public class Domain
{
    public int ID { get; set; }
    ...
}

and at the same time you have a route parameter called id in your Edit controller action:

public ActionResult Edit(Guid id)
{
    ...
}

Now here's what happens: The Html helpers (such as TextBoxFor, HiddenFor, ...) always first looks in the model state when binding a value (i.e. query string parameters, route values) and only at the end it looks at the value in the model. That's how all Html helpers work and it is by design.

So you have the following:

@Html.HiddenFor(model => model.ID)

The ID is taken NOT from the model but from your Route data (which is a Guid as specified in your action parameter). That's why it is very dangerous to use properties in the view model and action parameters that have the same name.

One possible workaround would be to rename your action parameter to something else:

public ActionResult Edit(Guid domainId)
{
    Domain domain = db.Domains.Single(d => d.GUID == domainId);
    return View(domain);
}

Of course now your routes might need to be adapted or use query string parameters: controller/edit?domainId=d578b4b7-48ec-4846-8a49-2120c17b6441 to invoke the Edit action.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文