簡體   English   中英

ASP.NET MVC中使用動態表單的建議

[英]Advice with Dynamic Forms in ASP.NET MVC

我正在ASP.NET MVC視圖中渲染動態表單,以滿足這些要求:

  • 可以驗證字段
  • 表單無效時保留狀態

我正在研究創建一個自定義模型綁定器來實現這一目標。 我一般打算這樣做:

  1. 表單字段使用這些屬性定義
    • 提示(字段旁邊的標簽)
    • 輸入(文本,復選框列表,放射學家等)
    • 選擇(列表字段)
    • 是必須的
    • RegularExpression(用於文本字段)
    • 顯示選項
    • 字段定義的集合從控制器發送到視圖
    • 字段將呈現為HTML並發送到瀏覽器
    • 表單將發送回服務器
    • 自定義模型綁定器將表單綁定到現在包含提交值的字段定義集合
    • 每個字段都經過驗證
    • 如果需要 - >必須有值
    • 如果RegEx - >必須匹配
    • 對於每個無效字段,都會向modelstate添加一條錯誤消息
    • 控制器決定做什么
    • 如果所有字段都有效
      • 對領域及其價值做任何事情
    • 如果1個或多個字段無效
      • 將字段集合發送回視圖
      • 使用先前嘗試的值再次渲染字段
      • 顯示驗證摘要

我不確定我是以最好還是最簡單的方式做這件事。 這種方法會給我帶來很多問題甚至工作嗎? 我該怎么做才能改進它?

我寫了一個類庫,基本上完全按照我的問題描述的psuedocode。 它很棒。

編輯:

我終於開始清理我的班級圖書館了。 我添加了一些新功能,並創建了一個記錄完備的演示Web應用程序。

所有這些都在CodePlex上托管 我希望這可以幫助別人。

我絕不是專家,但如果您是ASP.NET MVC的新手,那么我建議您在開始自己的內置功能之前先使用內置功能。 它完成了您所描述的大部分內容,但不鼓勵在控制器中定義/構建UI,因為這是視圖的工作。

通過ModelStateDictionary,您可以添加模型錯誤並設置模型值,然后在驗證失敗時綁定到表單輸入。

更新:另一種看待它的方法:問問自己為什么使用MVC而不是經典的ASP.NET構造技術,然后看看你提出的方法是否符合這些原因。 對我來說,分離關注點是一個很大的原因,以及對生成的HTML的細粒度控制,我覺得你的方法可能會顛覆這些事情。

要具體解決您的編輯問題:

第1步到第1步是針對MVC范例的。 第4步,很好。 步驟5到7是非常標准的MVC實踐,並且完全受框架支持。 例如, 執行簡單驗證(C#)顯示了錯誤消息的驗證和表示示例。

雖然不是專家,但我必須創建一個解決方案,其中我的主要對象有一個值列表。 讓我們稱之為對象A有一個映射在數據庫中的ApplicationValues列表。 ApplicationValues有一個Key(表單字段,例如PhoneNumber)和Value。

由於ApplicationValues是一個EntitySet,我必須創建get和set方法來正確處理設置特定的ApplicationValue。 我的數據庫中還有一個ApplicationRules列表,它定義了這些應用程序值可以采用的內容。

這是一段代碼,可以幫助您開發滿足您需求的解決方案。

public partial ApplicationValue
{
    public string Key;
    public string Value;
}

public partial ApplicationRule
{
    public string ValidationFormat;
    public string ValidationError;
    public bool Required;
}

public partial class A
{
    public void SetValue(string key, string value)
    {
        //ApplicationValues is the list of values associated to object A
        ApplicationValue v = ApplicationValues.SingleOrDefault
        (k => k.Key == key);

        //if we already have this value
        if (v != null)
        {   //...then we can simply set and return
            v.Value = value;
            return;
        }

        //else we need to create a new ApplicationValue
        v = new ApplicationValue
            {
                AffinityID = this.ID,
                Key = key,
                Value = value
            };

        ApplicationValues.Add(v);
    }

    public string GetValue(ApplicationField key)
    {
        return GetValue(key, String.Empty);
    }

    public string GetValue(ApplicationField key, string defaultValue)
    {
        if (ApplicationValues == null)
            return defaultValue;

        ApplicationValue value = ApplicationValues.SingleOrDefault
        (f => f.Key == key.ToString());

        return (value != null) ? value.Value : defaultValue;
    }

然后進行表單驗證,我遍歷ApplicationRules(定義是否需要字段,包含正則表達式等)並將其與FormCollection匹配。

public ActionResult Details(FormCollection form)
{
    IList<ApplicationRule> applicationRules = //get my rules from the DB

    if (!(ValidateApplication(applicationRules, form, a)))
    {
        ModelState.AddModelError("message", "Please review the errors below.");
        return View(a);
    }
    ...
}

private bool ValidateApplication(IList<ApplicationRule> applicationRules,
                                 FormCollection form, A a)
    {
        //loop through the application rules
        foreach (ApplicationRule ar in applicationRules)
        {
            //try and retrieve the specific form field value using the key
            string value = form[ar.Key];

            if (value == null)
                continue;

            //set the model value just in case there is an error
            //so we can show error messages on our form
            ModelState.SetModelValue(ar.Key, ValueProvider[ar.Key]);

            //if this rule is required
            if (ar.Required)
            {   //...then check if the field has a value
                if (String.IsNullOrEmpty(value))
                {
                    ModelState.AddModelError(ar.Key, "Field is required");
                    continue;
                }
            }

            //if this rule has a validation format
            if (!String.IsNullOrEmpty(ar.ValidationFormat))
            {   //...then check the value is of the correct format
                Regex re = new Regex(ar.ValidationFormat);

                if (!re.IsMatch(value))
                {
                    ModelState.AddModelError(ar.Key, ar.ValidationError);
                    continue;
                }
            }

            a.SetValue(ar.Key, value);
        }

        return ModelState.IsValid;
    }

您的字段定義有多動態? 如果它們不經常更改,則可以在創建定義后使用代碼dom生成模型和控制器。 我沒有在ASP.NET MVC中嘗試這個,但它可能是一個好方法。

http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx

本文使用代碼dom進行ActionLink生成。

http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx#comments

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM