簡體   English   中英

C#MVC CMS-自定義遠程驗證

[英]C# MVC CMS - Customising Remote Validation

在下面的鏈接中,我問了一個有關如何確保字段不包含相同值的問題(例如,當字段上存在唯一約束時,正確約束C#時會導致拋出異常)。 用我收到的答案,它解決了這個問題,但提出了另一個問題。

確保另一個記錄尚未包含相同的值

我現在遇到的主要問題是創建新視圖時。 驗證按預期進行。 簡而言之-系統需要檢查ViewName和ViewPath(路由)是否都是唯一的,因此需要搜索數據庫。

但是,當我編輯視圖時,驗證會再次生效(實際上不應該這樣做,因為顯然是因為您正在編輯視圖而已存在)。

我現在的問題是如何自定義遠程驗證,以使其在編輯和創建時都可以不同地工作。 雖然我們不能編輯視圖名稱以匹配現有視圖,但也不應僅僅因為它與當前視圖相同而停止保存當前視圖。

以下是我的模型(不是(希望)由工具生成的部分:-):

[MetadataType(typeof(IViewMetaData))]
public partial class View : IViewMetaData { }

public interface IViewMetaData
{
    [Required(AllowEmptyStrings = false, ErrorMessageResourceType = typeof(DALResources), ErrorMessageResourceName = "ErrorRequiredField")]
    [StringLength(50, ErrorMessageResourceType = typeof(DALResources), ErrorMessageResourceName = "ErrorLessThanCharacters")]
    [Display(ResourceType = typeof(DALResources), Name = "ViewName")]
    [Remote("IsViewNameAvailable", "Validation")]
    string ViewName { get; set; }

    [Required(AllowEmptyStrings = false, ErrorMessageResourceType = typeof(DALResources), ErrorMessageResourceName = "ErrorRequiredField")]
    [StringLength(400, ErrorMessageResourceType = typeof(DALResources), ErrorMessageResourceName = "ErrorLessThanCharacters")]
    [Display(ResourceType = typeof(DALResources), Name = "ViewPath")]
    [Remote("IsViewPathAvailable", "Validation")]
    string ViewPath { get; set; }

    [Display(ResourceType = typeof(DALResources), Name = "ViewContent")]
    string ViewContent { get; set; }
}

我遇到問題的部分是[Remote]驗證屬性,該屬性定義如下:

[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public class ValidationController : Controller
{
    private FRCMSV1Entities db = new FRCMSV1Entities();

    public JsonResult IsViewNameAvailable(View view)
    {
        bool isViewNameInvalid = db.View.Any(v => v.ViewName == view.ViewName && v.Id != view.Id);

        if (!isViewNameInvalid)
            return Json(true, JsonRequestBehavior.AllowGet);

        string suggestedViewName = string.Format(UI_Prototype_MVC_Resources.ErrorViewAlreadyExists, view.ViewName);

        for (int i = 1; i < 100; i++)
        {
            string altViewName = view.ViewName + i.ToString();
            bool doesAltViewNameExist = db.View.Any(v => v.ViewName == altViewName);
            if (!doesAltViewNameExist)
            {
                suggestedViewName = string.Format(UI_Prototype_MVC_Resources.ErrorViewNotAvailableTry, view.ViewName, altViewName);
                break;
            }
        }
        return Json(suggestedViewName, JsonRequestBehavior.AllowGet);
    }

    public JsonResult IsViewPathAvailable(View view)
    {
        bool doesViewPathExist = db.View.Any(v => v.ViewPath == view.ViewPath && v.Id != view.Id);

        if (!doesViewPathExist)
            return Json(true, JsonRequestBehavior.AllowGet);

        string suggestedViewPath = string.Format(UI_Prototype_MVC_Resources.ErrorViewAlreadyExists, view.ViewPath);

        for (int i = 1; i < 100; i++)
        {
            string altViewPath = view.ViewPath + i.ToString();
            bool doesAltViewPathExist = db.View.Any(v => v.ViewPath == altViewPath);
            if (!doesAltViewPathExist)
            {
                suggestedViewPath = string.Format(UI_Prototype_MVC_Resources.ErrorViewNotAvailableTry, view.ViewPath, altViewPath);
                break;
            }
        }
        return Json(suggestedViewPath, JsonRequestBehavior.AllowGet);
    }
}

問題是,驗證需要在創建和編輯上都相同。 它只需要對編輯進行額外的檢查以確保我們仍在引用相同的記錄,如果是這樣,則因為沒有錯,所以無需顯示驗證消息。

我的問題是:1.如何使它按預期工作。 2.我可以看到這兩種方法幾乎相同,這違反了DRY原理。 我如何才能使它更通用並簡化它。 但是,第一個問題確實是我想回答的問題,因為重構沒有用的東西沒有意義。

有關更多信息,以上代碼也是以下鏈接中代碼的編輯:

https://msdn.microsoft.com/zh-CN/library/gg508808(VS.98).aspx

謝謝你的幫助。

您需要添加一個參數以將模型的ID屬性作為AdditionalFields傳遞。 假設其int Id ,則

[Remote("IsViewPathAvailable", "Validation", AdditionalFields = "Id")]
public string ViewName { get; set; }

方法應該是

public JsonResult IsViewNameAvailable(string viewName, int? id)

請注意,在“ Edit視圖中,您為Id屬性包括了一個隱藏的輸入,因此其值將由jquery.validate遠程函數發布回去。

然后,您可以檢查id參數是否為null (即它是新的)或具有一個值(它是現有的),並調整查詢以適合。

bool isViewNameInvalid;
if (id.HasValue)
{
    isViewNameInvalid = db.View.Any(v => v.ViewName == viewName && v.Id != id);
}
else
{
    isViewNameInvalid = db.View.Any(v => v.ViewName == ViewName);
}

當前正在發生的事情是, Remote僅發布ViewName屬性的值,並且由於您的參數是模型,因此將使用默認的id值( 0 )對其進行初始化,並且您的查詢將轉換為Any(v => v.ViewName == viewName && v.Id != 0);

我還建議使用視圖模型,而不是partial class

附注:從生成的代碼suggestedViewName ,你的期望很高的ViewName以相同的值,這意味着在你里面你可能使眾多數據庫調用for循環。 您可以考慮使用linq .StartsWith()查詢來獲取所有以ViewName值開頭的記錄,然后檢查循環中設置的內存。

暫無
暫無

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

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