![](/img/trans.png)
[英]Remote Validation - No url for remote validation could be found mvc 5 C#
[英]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.