2

私は ASP.NET MVC3 を使用しており、いくつかのプロパティを持つビュー モデルを持っています。その一部はユーザーに表示するためのもので、一部はユーザーからの入力として使用され、既定値を持つ場合があります。GET リクエスト (唯一のパラメーターは何を取得するかの識別子です) と、ビュー モデル全体をアクションのパラメーターとして受け取る投稿に対して、同じビュー モデルを使用しています。私のコントローラーは、NHibernate セッションからエンティティーをプルするビジネス・ロジック・レイヤーを介して取得されたエンティティーをビュー・モデルに取り込みます。

すべての読み取り専用フィールドの非表示の入力をビューに配置して、無効なビューモデルを使用して投稿した後にページがレンダリングされた場合にそれらが表示されるようにする方が良いですか、それともユーザーが実際に使用する入力のみを使用する方が良いですか?データを提供し、残りのバックエンドをリロードしてマージしますか?

ありがとう!

編集:

なぜ?

編集:

コントローラーは通常、次のようになります。

public class MyController : BaseController /* BaseController provide BizLogic object */
{
    [HttpGet]
    public ActionResult EditSomething(Int32 id)
    {
        MyDomainObject = base.BizLogic.GetMyDomainObjectById(id);
        MyViewModel model = new MyViewModel();
        model.Id = id;
        model.ReadOnly1 = MyDomainObject.Field1;
        model.Readonly2 = MyDomainObject.Field2;
        model.UserInput3 = MyDomainObject.Field3;
        model.UserInput4 = MyDomainObject.Field4;
        return View(model);
    }

    [HttpPost]
    public ActionResult EditSomethingMyViewModel model)
    {
        PerformComplexValidationNotDoneByAttributes(model);
        if (ModelState.Valid)
        {
            BizLogicSaveTransferObject transferObject =
                new BizLogicSaveTransferObject();
            transferObject.Id = model.Id;
            transferObject.Field3 = model.UserInput3;
            transferObject.Field4 = model.UserInput4;
            base.BizLogic.SaveDomainObject(transferObject);

            return RedirectToAction("EditSomething", new { id = model.Id });
        }
        else
        {
            #if reload_non_input_fields_from_db

            MyDomainObject = base.BizLogic.GetMyDomainObjectById(model.Id);
            model.ReadOnly1 = MyDomainObject.Field1;
            model.Readonly2 = MyDomainObject.Field2;

            #endif

            return View(model);
        }
    }
}

ビューは次のようになります。

# Html.BeginForm();
${Html.ValidationSummary()}
    <p>ID: ${Model.Id}</p><input type="hidden" name="${Html.NameFor(m => m.Id)}" value="${Model.Id" />
    <p>Read Only One: ${Model.ReadOnly1}</p><!-- uncomment if not reload_non_input_fields_from_db <input type="hidden" name="${Html.NameFor(m => m.ReadOnly1)}" value="${Model.ReadOnly1}" />-->
    <p>Read Only Two: ${Model.ReadOnly2}</p><!-- uncomment if not reload_non_input_fields_from_db <input type="hidden" name="${Html.NameFor(m => m.ReadOnly2)}" value="${Model.ReadOnly2}" />-->
    <p>Input Three: ${Model.UserInput3}</p><input type="hidden" name="${Html.NameFor(m => m.UserInput3)}" value="${Model.UserInput3}" />
    <p>Input Three: ${Model.UserInput4}</p><input type="hidden" name="${Html.NameFor(m => m.UserInput3)}" value="${Model.UserInput4}" />
# Html.EndForm();
4

2 に答える 2

2

読み取り専用の場合(もちろん、一意のレコードIDフィールドを除く)、ページに入力を入力しても意味がありません。あなたが書いたように、ユーザーが変更を許可されているフィールドをマージします。

どちらの方法でもフィールドをマージする必要があります。読み取り専用フィールドの場合、クライアントに送信したデータに基づいて上書きしないでください。同じように返されると想定します。入力を「非表示」にしたとしても、実際には非表示にはなりません。たとえば、Firebugの使用方法を知っている人なら誰でも簡単に変更できます。

于 2012-09-11T20:54:52.450 に答える
0

私は Spark ビュー エンジンに詳しくありませんが、あなたのフォームは情報を表示するだけで、非表示のフィールドがあるように見えますか?

ただし、実際に達成しようとしているのは、ユーザーが UserInput3 と UserInput4 を編集できるようにすることだと思います。したがって、私はあなたのコントローラーとビューをあなたが達成しようとしていると思うものに書き直し、私の答えを含むコメントを含めました。ビューは razor ビュー エンジンを使用して記述されているため、Spark に転送する必要があります。

これがあなたが望んでいたものであることを願っています:

コントローラ:

//HttpGet has been removed as this is implied
public ViewResult EditSomething(Int32 id)
{
    MyDomainObject = base.BizLogic.GetMyDomainObjectById(id);
    MyViewModel model = new MyViewModel()  
    {
        //this uses C# 3.0 object initializer syntax
        model.Id = MyDomainObject.Id,
        model.ReadOnly1 = MyDomainObject.Field1,
        model.Readonly2 = MyDomainObject.Field2,
        model.UserInput3 = MyDomainObject.Field3,
        model.UserInput4 = MyDomainObject.Field4
    };
    return View(model);
}

//It is common (although not required) for the Post action to have the same name as the Get action
[HttpPost]
public ActionResult EditSomething (MyViewModel model)
{
    //I recommend you take a look at FluentValidation to validate your models.
    //Hopefully, you should no longer have the limitations of the data attributes and you will not require PerformComplexValidationNotDoneByAttributes()
    //This will allow you to just simply check the model state.
    if (ModelState.IsValid)
    {
        BizLogicSaveTransferObject transferObject = new BizLogicSaveTransferObject()
        {
            //You should write the new user inputs to the database.
            transferObject.Id = model.Id,
            transferObject.Field3 = model.UserInput3,
            transferObject.Field4 = model.UserInput4
        };
        base.BizLogic.SaveDomainObject(transferObject);

        //You were previously returning a redirect to the same action???  Do you need to pass the id?
        return RedirectToAction("NextAction", new { id = model.Id });
    }

    //Note: The else is not required as a return was used in the previous if.

    //IN ANSWER TO YOUR QUESTION, you should re-retrieve the domain object from the database to get the information to display again
    //as these values will be null/default values in your model.
    //There will be a performance cost in retrieving this information again but you could not rely on this data to be sent from the user.
    //Nor, should it have been included in the request as you should keep the size of the request down as indicated here:
    //http://developer.yahoo.com/performance/rules.html
    MyDomainObject = base.BizLogic.GetMyDomainObjectById(model.Id);
    model.ReadOnly1 = MyDomainObject.Field1;
    model.Readonly2 = MyDomainObject.Field2;

    return View(model);
}

意見:

@model MyViewModel

<!--
    The read only fields which are only used to display information have been included outside of the form.
    As this information is only used for display purposes we do not want to send it back as:
    1. It will increase the size of the request.
    2. We can not rely on it as a mischievous user may have tampered with it.
-->
<p>Read Only One: @Html.TextBoxFor(m => m.ReadOnly1)</p>
<p>Read Only Two: @Html.TextBoxFor(m => m.ReadOnly2)</p>

@using (Html.BeginForm())
{
    <!--
        The id is still passed using a hidden field as you still need to identify the database entity in the post action.
        I have not displayed the id as there seemed little point.
        Again, a user could change this id so you would need to check that the id exists in the database.
    -->
    @Html.HiddenFor(m => m.Id)

    <!--
        The user inputs do not need to have their previous values passed via hidden fields.
        This increases the size of the request and by the looks of it you are not using them in the post controller.
    -->
    <p>@Html.TextBoxFor(m => m.UserInput3)</p>
    <p>@Html.TextBoxFor(m => m.UserInput4)</p>

    <input type="submit" value="submit" />
}
于 2012-09-13T21:12:16.737 に答える