1

I am coding a MVC 5 internet application and have a question regarding validation in a view.

Here is my view code:

<div class="form-group">
    @Html.LabelFor(model => model.asset.linkFromExternalResource, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        <div class="checkbox">
            @Html.EditorFor(model => model.asset.linkFromExternalResource)
            @Html.ValidationMessageFor(model => model.asset.linkFromExternalResource, "", new { @class = "text-danger" })
        </div>
    </div>
</div>

<div class="form-group">
    @Html.LabelFor(model => model.asset.webAddress, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.asset.webAddress, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.asset.webAddress, "", new { @class = "text-danger" })
    </div>
</div>

<div class="form-group">
    @Html.LabelFor(model => model.fileId, "fileId", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownList("fileId", null, htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.fileId, "", new { @class = "text-danger" })
    </div>
</div>

How can I write the code to validate either the model.asset.webAddress or the model.fileId depending on if the model.asset.linkFromExternalResource is checked or not?

I will try and explain that better. If the user has the model.asset.linkFromExternalResource checkbox checked, then the model.asset.webAddress value will be validated, but not the model.fileId and if the model.asset.linkFromExternalResource checkbox is unchecked, then the model.asset.webAddress value will be not be validated, but the model.fileId will be validated.

How should I approach this situation? Do I write this code in the view, or in the controller?

EDIT

I have added MVC Foolproof Validation but am getting the following error:

[NotImplementedException: The method or operation is not implemented.]

At this line of code:

await db.SaveChangesAsync();

Rather than using MVC Foolproof Validation, is it easier to write my own custom validation attribute?

EDIT2

I have created a testModel, and a controller and the error still occurs.

Here is my model:

public class TestModel
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string name { get; set; }
    public bool testValue { get; set; }
    [RequiredIfTrue("testValue")]
    public string value1 { get; set; }
    [RequiredIfFalse("testValue")]

    public string value2 { get; set; }
}

Here is the controller:

public ActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Id,name,testValue,value1,value2")] TestModel testModel)
{
    if (ModelState.IsValid)
    {
        db.testModels.Add(testModel);
        await db.SaveChangesAsync();
        return RedirectToAction("Index");
    }

    return View(testModel);
}

Here is the error:

Server Error in '/' Application.

The method or operation is not implemented.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.NotImplementedException: The method or operation is not implemented.

Source Error: 


Line 54:             {
Line 55:                 db.testModels.Add(testModel);
Line 56:                 await db.SaveChangesAsync();
Line 57:                 return RedirectToAction("Index");
Line 58:             }

Source File: e:\CanFindLocation\MVC\CanFindLocation\CanFindLocation\Controllers\TestModelsController.cs    Line: 56 

Stack Trace: 


[NotImplementedException: The method or operation is not implemented.]
   Foolproof.ModelAwareValidationAttribute.IsValid(Object value) +59
   System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value, ValidationContext validationContext) +115
   System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext) +29
   System.Data.Entity.Internal.Validation.ValidationAttributeValidator.Validate(EntityValidationContext entityValidationContext, InternalMemberEntry property) +198

[DbUnexpectedValidationException: An unexpected exception was thrown during validation of 'value1' when invoking Foolproof.RequiredIfTrueAttribute.IsValid. See the inner exception for details.]
   System.Data.Entity.Internal.Validation.ValidationAttributeValidator.Validate(EntityValidationContext entityValidationContext, InternalMemberEntry property) +299
   System.Data.Entity.Internal.Validation.PropertyValidator.Validate(EntityValidationContext entityValidationContext, InternalMemberEntry property) +148
   System.Data.Entity.Internal.Validation.EntityValidator.ValidateProperties(EntityValidationContext entityValidationContext, InternalPropertyEntry parentProperty, List`1 validationErrors) +203
   System.Data.Entity.Internal.Validation.TypeValidator.Validate(EntityValidationContext entityValidationContext, InternalPropertyEntry property) +105
   System.Data.Entity.Internal.Validation.EntityValidator.Validate(EntityValidationContext entityValidationContext) +55
   System.Data.Entity.Internal.InternalEntityEntry.GetValidationResult(IDictionary`2 items) +295
   System.Data.Entity.DbContext.ValidateEntity(DbEntityEntry entityEntry, IDictionary`2 items) +86
   System.Data.Entity.DbContext.GetValidationErrors() +290
   System.Data.Entity.Internal.InternalContext.SaveChangesAsync(CancellationToken cancellationToken) +150
   System.Data.Entity.Internal.LazyInternalContext.SaveChangesAsync(CancellationToken cancellationToken) +75
   System.Data.Entity.DbContext.SaveChangesAsync(CancellationToken cancellationToken) +60
   System.Data.Entity.DbContext.SaveChangesAsync() +63
   CanFindLocation.Controllers.<Create>d__7.MoveNext() in e:\CanFindLocation\MVC\CanFindLocation\CanFindLocation\Controllers\TestModelsController.cs:56
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21
   System.Threading.Tasks.TaskHelpersExtensions.ThrowIfFaulted(Task task) +61
   System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +114
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeAsynchronousActionMethod>b__36(IAsyncResult asyncResult) +66
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +47
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +136
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +49
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +117
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +323
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +44
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +47
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +136
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +102
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +50
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +72
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +185
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +42
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +133
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +56
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +40
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +34
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +39
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +62
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +39
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
   System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9651116
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
Simon
  • 7,991
  • 21
  • 83
  • 163
  • You could look at using [Foolproof Validation](https://foolproof.codeplex.com/) `RequiredIfTrue` and `RequiredIfFalse` attributes –  Oct 13 '14 at 05:21
  • Stephen, can you please have a look at my edit? – Simon Oct 14 '14 at 04:02
  • That looks to be a completely different issue. If both client and server side validation is working (i.e you get errors display in the browser or `ModelState` is not valid on the server) if you post invalid data, then I don't the attributes are the problem. Does the error occur if you remove the attributes? –  Oct 14 '14 at 04:08
  • The error does not occur if I remove the attributes. – Simon Oct 14 '14 at 04:12
  • Here is a web resource for the same error: http://forums.asp.net/t/1752975.aspx – Simon Oct 14 '14 at 04:16
  • You will need to post details of you model and controller, but `@Html.DropDownList("fileId", null, ..)` may be an issue (Your really should use the strongly typed helper and pass a `SelectList`). And are you using a view model or adding the attributes to you data model? –  Oct 14 '14 at 04:20
  • Can you have a look at my edit? – Simon Oct 14 '14 at 04:38
  • OK, there is clearly an issue with foolproof in conjunction with EF. You can overcome this easily enough by creating a [view model](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) (which is best practice anyway) that contains only the properties you want to edit and add the attributes to the view model properties (not the data model). Tools such as [automapper](https://automapper.codeplex.com/) make it easier to map you data model to the view model. –  Oct 14 '14 at 05:01

0 Answers0