web-dev-qa-db-ja.com

ASP.NET MVC-作成と編集の両方に同じフォームを使用する

新しいモデルの作成と既存のモデルの編集の両方に使用されるフォームを作成するためのベストプラクティスアプローチは何ですか?

人々が私に指示することができるチュートリアルはありますか?

42

同じコントローラを使用しないでくださいaction。 New = HTTP POST; edit = HTTP PUT、それは2つの異なることです。ただし、両方のアクションは同じコントローラー上に存在することができます。

一般的な機能(エディターなど)にユーザーコントロールを使用し、それをアクション固有のビューにラップして、新規または編集ではなく、両方に表示する必要があるもののアイデアを気に入っています。

8
Craig Stuntz

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()を使用していることを考慮に入れてください。これは、すべてのフィールドを一度に生成する革新的な方法であり、使用する前にその欠点を研究する必要があります。ただし、残りの例を簡単に使用して、共通のフォームを作成および編集ビューから分離できます。

最後に、興味がある場合は コントローラコードはこちら を表示できます。

37
Mariano Desanze
11
E Rolnicki

仮定

  1. これは、ユーザーがブラウザーでさまざまなアクションに対してさまざまなURLを表示するのに適しています。たとえば、「/ pages/create」や「​​/ pages/edit/1」などです。

  2. 通常、ページは非常によく似ているため、ページの作成と編集の両方にアクションとビューのペアを1つだけ持つことは、開発者にとっては良いことです。 (また、これはエンティティごとに1つのコントローラーを持つのに適しています。)

ソリューション

デフォルトのルート登録は '{controller}/{action}/{id}'です。さらに2つのルールbeforeを追加できます。

{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」アクションによって処理されます。その他はデフォルトの方法になります。

次に、コントローラーでHttpGetおよびHttpPostの「CreateOrEdit」アクションを追加します。

[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(既存のページを削除するため)

私はそれが誰かを助けることを願っています!

6
Dmitry Sikorsky

(IMOである必要があります)1つのコントローラーであっても、コントローラーのアクションが異なる場合があります。また、適切なアクションに関連付けられた適切なHTTP動詞があることを確認してください。 E Rolnickiが投稿したチュートリアルに従ってください。

ハッピーコーディング!!

1
Perpetualcoder

これはケースに依存するため、常にベストプラクティスであるとは限りません。

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 /編集と作成のビューを1つのビューに結合し、Creeditを呼び出します

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

2つのビューと4つのアクションの代わりに、1つのビューと2つのアクション(1つの投稿と1つの取得)があります。

1
Chtiwi Malek

エンティティにある種の内部秘密鍵(たとえば、常に0より大きい「id」メンバー)がある場合、/ Createの代わりに/ Edit/0を使用できます。

0
Serge Wautier

フォーム自体をユーザーコントロールに配置します(たとえば、Views/Shared/WidgetForm.ascx)。すべてのフォームフィールドをこのユーザーコントロールに配置しましたが、フォームタグ自体は配置していません。

Views/Widgets/New.aspxやViews/Widgets/Edit.aspxなどのビューには、フォームタグとすべての「周囲」-フォーム、ページタイトルなどの入力手順などが含まれています。次に、フォームタグ内のユーザーコントロール。

ユーザーコントロールはWidgetオブジェクトを受け取り、結果に基づいてフォームを表示するだけです。そのため、新しいウィジェットオプションに適切なデフォルトを設定することが重要になりますが、とにかくそうしますか? ;)

0
Keith Williams

私はかなりうまくいくと思うシステムを持っています。私の共有ビューには、Edit.aspxとNew.aspxの2つの汎用フォームがあります。

次に、特定のビューフォルダーにEditItems.ascxという名前のコントロールがあります。

私の編集フォームには、フォームタグと編集用の特定のボタンがあり、新しいフォームには、フォームタグと新しい特定のボタンがあります。それぞれにHtml.RenderPartial( "EditItems.ascx")があります

このようにして、ユーザーコントロールを強く型付けできますが、編集ページと新しいページのルックアンドフィールを再利用しています。

場合によっては、新しいページのレイアウトが編集ページと異なる場合があります。その場合は、「Edit.aspx」を特定のビューフォルダーに追加するだけです。

これにより、再利用の最適な組み合わせが得られ、必要に応じて完全なカスタマイズが可能になります。そしてコントローラーのアクションに関しては、はい、それらは別々のアクションであるべきです。

0

私はのようなものを使用します

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

そして

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

それはうまくいくようです。

0
ChrisFox