2

We're busy writing an app that makes use of on-the-fly validation (onBlur, onClick, etc.) and also validation on form submission. The "on-the-fly" check and form submit re-uses the same code to validate the user's input. This is done via MVC's IValidatableObject interface, which requires you to override the Validate method to house the validation code.

Along with this, I was able to incorporate a Validation Attribute that checks the ModelState before entering the Controller method's actual implementation:

[HttpPost]
[ValidateModel]
public void ValidateMyModel([FromBody] SomeModel model)
{
}

[HttpPost]
[ValidateModel]
public void SubmitMyModel([FromBody] SomeModel model)
{
   // Some code here
}

All of this runs correctly and as expected.

The issue I have is, because one Controller method is specifically catered to run validation (the "on-the-fly" manner) and another is entirely devoted to actually submitting the form, there is no code needed to run inside the Controller method that does pure validation. This ends up with the body of the method being empty. This is not clean code design and yet re-using the validation code via the Attributes is. I'm also rather loathe to just run the "Validate only" scenario with the submission code included because that blurs its purpose.

My question thus is, is there a way in MVC to run the validation on the model, without necessarily declaring a controller method, whilst still being accessible via an asynchronous HTTP request?

7
  • 1
    What is the design reason for wanting to validate the model server side in this fashion before the real submission? If you want to do an initial validation, just do it client side and save the round trip. You can't rely on the client not changing the data between the initial server side one and the actual POST, so you're left validating it on the server for the "real" submission anyway. Commented Oct 9, 2017 at 14:54
  • Usually I'd agree with you, but for this particular project there's quite a bit of IP that needs to be hidden behind the server, so client-side validation isn't possible. Obviously some bits are such as "required" and so on, but very little else. This "on-the-fly" validation is done due to user expectations Commented Oct 9, 2017 at 14:56
  • Fair enough! The only other way I can think of to remove the empty actions would be to put another property on the model (eg bool JustValidate) that you can check and return early in the actual submission, but that really just shifts your boiler plate code somewhere else and pollutes your models. I'll be interested to see if there's any other alternatives too... Commented Oct 9, 2017 at 15:00
  • As James Thorpe suggested you could expand the model with a boolean flag marking if the action was called for validation or if it was submitted. Depending how the data is submitted you could also check the ViewContext. Not sure if this works but to remove the condition in your method you could create a custom attribute. Commented Oct 9, 2017 at 15:10
  • 1
    the only way to have something accessible via a HTTP request in MVC is via a controller method. You say "This is not clean code", but why? You've got two methods with different purposes which are exposed to the client, but both share the same re-usable code to do the parts which they both need. There's no duplication of business or validation logic that I can see, and no verbose or awkward workarounds. IMHO it actually works quite nicely as it is. Commented Oct 9, 2017 at 15:47

1 Answer 1

1

The only way to have something accessible via a HTTP request in MVC is via a controller method.

You say "This is not clean code", but why? You've got two methods with different purposes which are exposed to the client, but both share the same re-usable code to do the parts which they both need. There's no duplication of business or validation logic that I can see, and no verbose or awkward workarounds.

IMHO it actually works quite nicely as it is, and I wouldn't change your approach.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.