Подтвердить что ты не робот

ASP.NET MVC - использование одной и той же формы для создания и редактирования

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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(), который является инновационным методом для генерирования всех полей одновременно, и перед его использованием вы должны изучить его недостатки. Но вы можете легко взять остальную часть примера, чтобы отделить вашу общую форму от представлений создания и редактирования.

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

Ответ 4

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

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

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

Решение

Регистрация маршрутов по умолчанию - '{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 (для удаления существующей страницы)

Я надеюсь, что это поможет кому-то!

Ответ 5

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

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

Ответ 6

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

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 действия.

Ответ 7

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

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

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

Ответ 8

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

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

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

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

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

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

Ответ 9

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

Ответ 10

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

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

и

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

Это работает нормально.