At the link below I asked a question about how to ensure a field does not already contain the same value (for example when there is a unique constraint on a field which correctly causes C# to throw an exception when voilated). With the answer I received, it solved that problem but presented another.
Ensuring another record does not already contain the same value for a field
The main issue I now have is that when I create a new View. The validation works as expected. In brief - The system needs to check that the ViewName and ViewPath (route) are both unique so a search of the DB is required.
However, when I edit the view, the validation kicks in again (and it actually should not because obviously the view exists already because you are editing it).
My issue now is how do I customise the remote validation to work differently for edit vs create. While we should not be able to edit the name of a view to match an existing view, we should also not be stopped from saving the current view simply because it is the same as the current view.
Below is my Model (the part that is not (hopefully) generated by a tool :-):
[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; }
}
The part I am having a problem with is the [Remote] validation attribute which is defined below:
[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);
}
}
The problem is, the validation needs to work the same on both create and edit. It just needs to do an additional check on edit to ensure we are still referring to the same record and if so, then there is no need to show the validation message because there is nothing wrong.
My question is: 1. How do I get this to work as expected. 2. I can see that both methods are pretty much identical, which violates the DRY principle. How can I make this more generic and simplify it. However the first question is really the one I would like answered because there is no point in refactoring something that doesn't work.
For more information, the above code is also an edit of the code at the following link:
https://msdn.microsoft.com/en-us/library/gg508808(VS.98).aspx
Thanks for any help.
See Question&Answers more detail:os