ASP.NET MVC - использование одной и той же формы для создания и редактирования - PullRequest
42 голосов
/ 30 декабря 2008

Каков наилучший практический подход к созданию формы, которая используется как для создания новых моделей, так и для редактирования существующих моделей?

Есть ли какие-нибудь учебные пособия, на которые люди могут указывать мне в направлении?

Ответы [ 10 ]

37 голосов
/ 02 февраля 2011

NerdDinner будет действительно укажет путь.

Create.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>" MasterPageFile="~/Views/Shared/Site.Master"  %>
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Host a Nerd Dinner
</asp:Content>
<asp:Content ID="Create" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Host a Dinner</h2>
    <% Html.RenderPartial("DinnerForm"); %>
</asp:Content>

Edit.aspx

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<NerdDinner.Models.Dinner>"
    MasterPageFile="~/Views/Shared/Site.Master" %>
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Edit: <%:Model.Title %>
</asp:Content>
<asp:Content ID="Edit" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Edit Dinner</h2>
    <% Html.RenderPartial("DinnerForm"); %>
</asp:Content>

DinnerForm.ascx

<%@ Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NerdDinner.Models.Dinner>" %>
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
<% Html.EnableClientValidation(); %>
<%: Html.ValidationSummary("Please correct the errors and try again.") %>
   <% using (Html.BeginForm())
      { %>
   <fieldset>
       <div id="dinnerDiv">
           <%:Html.EditorForModel() %>
           <p>
               <input type="submit" value="Save" />
           </p>
       </div>
       <div id="mapDiv">
           <%: Html.EditorFor(m => m.Location) %>
       </div>
   </fieldset>
   <% } %>

Примите во внимание, что эта форма использует Html.EditorForModel(), который является инновационным методом для генерации всех полей одновременно, и вы должны изучить его недостатки перед использованием. Но вы можете легко взять оставшуюся часть примера, чтобы отделить вашу общую форму от представлений создания и редактирования.

Наконец, вы можете просмотреть код контроллера здесь , если вы заинтересованы.

11 голосов
/ 30 декабря 2008
8 голосов
/ 30 декабря 2008

Не использовать тот же контроллер действие. New = HTTP PUT; edit = HTTP POST, так что это две разные вещи. Оба действия могут и должны быть на одном контроллере.

Мне нравится идея использовать пользовательский элемент управления для общих функций (например, редакторов) и включать его в специфичные для действий представления для элементов, которые должны появляться только в новом или редактируемом, но не в обоих.

5 голосов
/ 27 марта 2015

Предположения

  1. Это удобно для пользователя, чтобы увидеть разные URL-адреса для различных действий в браузере. Например, «/ pages / create» и «/pages/edit/1» .

  2. Для разработчика полезно иметь только одну пару действие + вид для создания и редактирования страниц, поскольку они обычно очень похожи. (Также хорошо иметь один контроллер на объект.)

Решение

Регистрация маршрутов по умолчанию: '{controller} / {action} / {id}' Мы можем добавить еще два правила перед этим:

{controller} / create (должен указывать на действие «CreateOrEdit»)

{controller} / edit / {id} (также должен указывать на действие «CreateOrEdit»)

Теперь у нас может быть что-то вроде этого:

public static void RegisterRoutes(RouteCollection routes)
{
  routes.MapRoute(
    name: "Create",
    url: "{controller}/create",
    defaults: new { controller = "Default", action = "CreateOrEdit" }
  );

  routes.MapRoute(
    name: "Edit",
    url: "{controller}/edit/{id}",
    defaults: new { controller = "Default", action = "CreateOrEdit" }
  );

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

Так что теперь и запросы на создание и редактирование будут обрабатываться действием 'CreateOrEdit'. Другие пойдут по умолчанию.

Следующее, что мы должны сделать, это добавить действие 'CreateOrEdit' для HttpGet и HttpPost в нашем контроллере:

[HttpGet]
public ActionResult CreateOrEdit(int? id)
{
  return this.View(new CreateOrEditViewModelBuilder(this).Build(id));
}

[HttpPost]
public ActionResult CreateOrEdit(CreateOrEditViewModel сreateOrEditViewModel)
{
  if (this.ModelState.IsValid)
  {
    Page page = new CreateOrEditViewModelMapper(this).Map(сreateOrEditViewModel);

    if (сreateOrEditViewModel.Id == null)
      this.UnitOfWork.GetRepository<IPageRepository>().Create(page);

    else this.UnitOfWork.GetRepository<IPageRepository>().Edit(page);

    this.UnitOfWork.Save();
    return this.RedirectToAction("Index");
  }

  return this.View(сreateOrEditViewModel);
}

И, наконец, мы должны добавить представление с именем «CreateOrEdit». Мы можем использовать здесь this.Model.Id == null, чтобы узнать, что мы создаем или редактируем.

Результат

Теперь у нас нет повторяющегося кода, и мы можем иметь такие очевидные URL, как этот:

/ pages (чтобы увидеть все страницы)

/ pages / create (создать новую страницу)

/ pages / edit / 1 (для редактирования существующей страницы)

/ pages / delete / 1 (чтобы удалить существующую страницу)

Надеюсь, это кому-нибудь поможет!

1 голос
/ 24 июня 2013

это не всегда лучшая практика, потому что это зависит от случая, вот как я это сделал

1 / я объединил действия контроллера для создания и редактирования

public PartialViewResult Creedit(string id = null)
{
    if (id == null)
    {
        // Create new record (this is the view in Create mode)
        return PartialView();
    }
    else
    {
        // Edit record (view in Edit mode)
        Client x = db.ClientSet.Find(id);
        if (x == null) { return PartialView("_error"); }
        // ...
        return PartialView(x);
    }
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Creedit(Client x)
{
    if (x.id == null)
    {
        // insert new record
    }
    else
    {
        // update record
    }
}

2 / Я соединил редактирование и создание представлений в одном представлении, которое я называю Creedit

// if you need to display something unique to a create view
// just check if the Model is null
@if(Model==null){
}

поэтому у меня есть 1 просмотр и 2 действия (1 сообщение и 1 получение) вместо 2 просмотров и 4 действия.

1 голос
/ 30 декабря 2008

Это может быть (должен быть IMO) один контроллер, но разные действия контроллера. Также убедитесь, что у вас есть правильные HTTP-глаголы, связанные с соответствующим действием. Следуйте инструкциям E Rolnicki, и вы уже в пути!

Счастливое кодирование !!

0 голосов
/ 15 июля 2012

Я использую что-то вроде

[HttpGet]
public ActionResult EntityEdit(Guid id)
{
    return View();
}

и

[HttpGet]
public ActionResult EntityCreate()
{
   return View("EntityEdit");
}

Кажется, все в порядке.

0 голосов
/ 08 сентября 2010

Если у сущности есть какой-то внутренний закрытый ключ (например, элемент «id», который всегда> 0), вы можете использовать / Edit / 0 вместо / Create

0 голосов
/ 31 декабря 2008

У меня есть система, которая, я думаю, работает довольно хорошо. В моих общих представлениях у меня есть 2 общие формы, Edit.aspx и New.aspx

Тогда в папке моего конкретного представления у меня есть элемент управления с именем EditItems.ascx

В моей форме редактирования у меня есть теги формы и определенные кнопки для редактирования, а в новой форме у меня есть теги формы и специальные кнопки для нового. В каждом у меня есть Html.RenderPartial ("EditItems.ascx")

Таким образом, ваш пользовательский элемент управления может быть строго напечатан, и все же вы повторно используете внешний вид редактирования и новых страниц.

Теперь в некоторых случаях ваша новая страница может иметь другой макет, чем страница редактирования. В этом случае просто добавьте «Edit.aspx» в вашу конкретную папку просмотра.

Я считаю, что это дает мне лучшую комбинацию повторного использования, и в то же время позволяет полностью настраивать меня, если мне это нужно. А что касается действий контроллера, то они должны быть отдельными действиями.

0 голосов
/ 30 декабря 2008

Я поместил саму форму в пользовательский элемент управления - скажем, Views / Shared / WidgetForm.ascx. Я поместил все поля формы в этот пользовательский элемент управления, но НЕ сами теги формы.

Представления, скажем Views / Widgets / New.aspx и Views / Widgets / Edit.aspx, содержат теги формы и все «окружение» - инструкции по заполнению формы, заголовок страницы и т. Д. они включают в себя пользовательский элемент управления внутри тегов формы.

Пользовательский элемент управления просто берет объект Widget и отображает форму на основе результатов. Поэтому использование разумных значений по умолчанию в новых настройках виджетов становится важным, но вы все равно делаете это, верно? ;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...