asp.net mvc леса и GUID в качестве первичного ключа - PullRequest
2 голосов
/ 20 июля 2011

У меня есть таблица со следующей структурой

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

Я создал Entity Model, используя Visual Studio, и сгенерировал представления для редактирования / удаления и т. Д. (Mvc scaffolding)

Проблемапри «Редактировании», когда я нажимаю эту ссылку, отображается соответствующая форма с правильными данными, но кнопка «Сохранить» не работает вообще.Обратите внимание, что другие ссылки (удаление, создание, детали) работают отлично.

Так что, когда я нажимаю ссылку "Изменить", URL-адрес

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

и форма отображается правильно, но кнопка сохранения не работает, никакой сетевой активности не происходит.Что-то особенное в использовании уникальных идентификаторов в качестве первичного ключа?

Спасибо

--- Код ---

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Я добавил следующий код в 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>

к моему удивлению (или невежеству) - вместо идентификатора GUID is shown as ID

отображается GUID, а кроме того - когдаЯ ввожу значение в это поле (1,2 или любое целое число), но все равно получаю сообщение «Идентификатор поля должен быть числом».

1 Ответ

7 голосов
/ 20 июля 2011

Проблема связана с тем, что у вас есть свойство с именем ID в вашей модели представления:

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

, и в то же время у вас есть параметр маршрута с именем id в вашем Edit контроллередействие:

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

Теперь вот что происходит: помощники HTML (такие как TextBoxFor, HiddenFor, ...) всегда сначала проверяют состояние модели при привязке значения (то есть параметров строки запроса, значений маршрута)и только в конце он смотрит на значение в модели.Вот как работают все Html-помощники, и это по своему замыслу.

Итак, у вас есть следующее:

@Html.HiddenFor(model => model.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, чтобы вызвать действие Edit.

...