c# MVC CMS -自定义远程验证
本文关键字:验证 程验证 MVC CMS 自定义 | 更新日期: 2023-09-27 18:05:04
在下面的链接中,我问了一个关于如何确保字段不已经包含相同值的问题(例如,当字段上有一个唯一的约束时,该约束正确地导致c#在违反时抛出异常)。对于我收到的答案,它解决了那个问题,但提出了另一个问题。
确保另一条记录不包含字段
的相同值我现在的主要问题是,当我创建一个新的视图。验证按预期工作。简而言之-系统需要检查ViewName和ViewPath (route)是否都是唯一的,因此需要搜索DB。
然而,当我编辑视图时,验证再次启动(实际上不应该,因为显然视图已经存在,因为你正在编辑它)。
我现在的问题是如何自定义远程验证以不同的方式进行编辑和创建。虽然我们不应该编辑视图的名称来匹配现有视图,但我们也不应该仅仅因为当前视图与当前视图相同而阻止保存当前视图。
下面是我的模型(不是(希望)由工具生成的部分:-):
[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; }
}
我有一个问题的部分是[远程]验证属性,定义如下:
[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);
}
}
问题是,验证需要在创建和编辑上工作相同。它只需要对edit做一个额外的检查,以确保我们仍然引用相同的记录,如果是这样,则不需要显示验证消息,因为没有任何错误。
我的问题是:1. 我如何让这个工作如预期。2. 我可以看到这两种方法几乎相同,这违反了DRY原则。我怎样才能使它更通用,更简单。然而,第一个问题是我真正想要回答的,因为重构不能工作的东西是没有意义的。
要了解更多信息,上面的代码也是以下链接中代码的编辑:
https://msdn.microsoft.com/en-us/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返回。验证远程功能。
你可以检查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
值开始的所有记录,然后检查循环中的内存集。