问题
Description:
I have a simple form in an MVC4 application that has 5 textboxes named loc1-5 and a submit button. The application takes up to 5 addresses in the textboxes loc1-5 and uses the bing geocode services with jQuery to do some processing on the addresses and create a map with directions.
The issue is that I need to validate the loc1-5 textboxes to ensure that they are valid addresses before continuing and decided that the best way that makes sense is to use jQuery.validate with a remote call to an MVC controller function that can use my prebuilt functions to check for a valid address.
Now I did come up with a working solution to validate these fields but I desperately need to make it more dynamic so that in the future more textboxes can be added with minimal effort. Ideally I would like the logic to work something like validate on all inputs that start with 'loc'.
Working solution (very dirty):
Simple form (in MVC view)
<form action="/Home/ViewResult" method="post" id="ViewResult" name="ViewResult">
<fieldset>
<legend>Enter Route</legend>
<p>
Address 1 (Start & End):
</p>
<p>
<input type="text" id="loc1" name="loc1" value='' />
</p>
<p>
Address 2:
</p>
<p>
<input type="text" id="loc2" name="loc2" value='' />
</p>
<p>
Address 3:
</p>
<p>
<input type="text" id="loc3" name="loc3" value='' />
</p>
<p>
Address 4:
</p>
<p>
<input type="text" id="loc4" name="loc4" value='' />
</p>
<p>
Address 5:
</p>
<p>
<input type="text" id="loc5" name="loc5" value='' />
</p>
<p>
<input type="submit" value="Route"/>
</p>
</fieldset>
</form>
jQuery validation code (in MVC view)
<script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () { $("#ViewResult").validate({ onfocusout: false, onkeyup: false, rules: { "loc1": { required: true, remote: { url: "/Home/IsValidAddress1", timeout: 2000, type: "post" } }, "loc2": { required: true, remote: { url: "/Home/IsValidAddress2", timeout: 2000, type: "post" } }, "loc3": { required: true, remote: { url: "/Home/IsValidAddress3", timeout: 2000, type: "post" } }, "loc4": { remote: { url: "/Home/IsValidAddress4", timeout: 2000, type: "post" } }, "loc5": { remote: { url: "/Home/IsValidAddress5", timeout: 2000, type: "post" } } }, messages: { "loc1": { required: "Start/End Location is a required field.", remote: "Please enter a valid address." }, "loc2": { required: "Please enter at least 3 addresses.", remote: "Please enter a valid address. " }, "loc3": { required: "Please enter at least 3 addresses.", remote: "Please enter a valid address. " }, "loc4": { remote: "Please enter a valid address. " }, "loc5": { remote: "Please enter a valid address. " }, } }); });
</script>
Functions in Home Controller referenced by remote
// Function to check for a valid address public Boolean IsValidAddress(string location) { // If it is not blank if (location != "") { // Attempt to get the waypoint Waypoint waypoint = getWaypoint(location); // If no waypoint returned, return false if (waypoint == null) { return false; } } return true; } public JsonResult isValidAddress1(string loc1) // Parameter must be textbox name { if (!IsValidAddress(loc1)) { return new JsonResult { Data = false }; } return new JsonResult { Data = true }; } public JsonResult isValidAddress2(string loc2) // Parameter must be textbox name { if (!IsValidAddress(loc2)) { return new JsonResult { Data = false }; } return new JsonResult { Data = true }; } public JsonResult isValidAddress3(string loc3) // Parameter must be textbox name { if (!IsValidAddress(loc3)) { return new JsonResult { Data = false }; } return new JsonResult { Data = true }; } public JsonResult isValidAddress4(string loc4) // Parameter must be textbox name { if (!IsValidAddress(loc4)) { return new JsonResult { Data = false }; } return new JsonResult { Data = true }; } public JsonResult isValidAddress5(string loc5) // Parameter must be textbox name { if (!IsValidAddress(loc5)) { return new JsonResult { Data = false }; } return new JsonResult { Data = true }; }
PROBLEM:
Again this works but it is very dirty and is not at all dynamic.
Essentially I have two issues.
- How can I write the jQuery shorthand to create a validation rule for all textboxes starting with "loc"?
- As far as I can tell the MVC controller function that handles the remote call must have the name of the textbox passed to it. So how can I have one MVC controller function handle multiple remote calls to it?
I am not very strong in jQuery but what I would really want is something like this so I can add more textboxes later with minimal effort:
<script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () { $("#ViewResult").validate({ onfocusout: false, onkeyup: false, rules: { "loc1": { required: true, }, "loc2": { required: true, }, "loc3": { required: true, }, $("input=text").StartsWith("loc").each(): { remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post" } } }, messages: { "loc1": { required: "Start/End Location is a required field.", }, "loc2": { required: "Please enter at least 3 addresses.", }, "loc3": { required: "Please enter at least 3 addresses.", }, $("input=text").StartsWith("loc").each(): { remote: "Please enter a valid address. " }, } }); });
</script>
And the Home Controller functions
// Function to check for a valid address public JsonResult IsValidAddress(string loc) // loc variable connect to dynamic textbox names? { // If it is not blank if (loc != "") { // Attempt to get the waypoint Waypoint waypoint = getWaypoint(loc); // If no waypoint returned, return false if (waypoint == null) { return new JsonResult { Data = false }; } } return new JsonResult { Data = true }; }
Finally note that I do not have the ability to change the MVC Model. I have seen many solutions similar to this that write the validation rules and remote calls directly in the MVC model, but I simply cannot do it that way.
Any suggestions for improvement are welcome and thanks in advance for any responses.
Please try and tell me where I went wrong or if what I want is even possible.
回答1:
So I figured it out.
Final working solution:
function in MVC Home Controller:
// Function to check for a valid address // Note: address variable parameter connects to data attribute in remote call public JsonResult IsValidAddress(string address) { // If it is not blank if (address != "") { // Attempt to get the waypoint Waypoint waypoint = getWaypoint(address); // If no waypoint returned, return false if (waypoint.Location == null) { return new JsonResult { Data = false }; } } return new JsonResult { Data = true }; }
jQuery functions in View:
<script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () { $("#ViewResult").validate({ onfocusout: false, onkeyup: false }); $("#loc1").rules("add", { required: true, messages: { required: "Start/End Location is a required field.", } }); $("#loc2").rules("add", { required: true, messages: { required: "Please enter at least 3 addresses." } }); $("#loc3").rules("add", { required: true, messages: { required: "Please enter at least 3 addresses." } }); $('#ViewResult [name^="loc"]').each(function () { var currentValue = null; currentValue = $(this); $(this).rules("add", { remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return currentValue.val(); } } }, messages: { remote: "Please enter a valid address." } }); }); });
</script>
I took so much time trying to figure this out that I thought I would share.
回答2:
So I was able to figure out the 2nd part of the problem by using the data attribute of the remote call inside the rule declaration to define a new parameter called 'address' which is then referenced as a parameter in the MVC controller function.
Here is the updated code for the MVC controller function in the Home controller:
// Function to check for a valid address // Note: address variable parameter connects to data attribute in remote call public JsonResult IsValidAddress(string address) { // If it is not blank if (address != "") { // Attempt to get the waypoint Waypoint waypoint = getWaypoint(address); // If no waypoint returned, return false if (waypoint.Location == null) { return new JsonResult { Data = false }; } } return new JsonResult { Data = true }; }
For the jQuery there are 2 ways to do it which both work.
Firstly using the format that I used previously:
<script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () { $("#ViewResult").validate({ onfocusout: false, onkeyup: false, rules: { "loc1": { required: true, remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc1").val(); } } } }, "loc2": { required: true, remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc2").val(); } } } }, "loc3": { required: true, remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc3").val(); } } } }, "loc4": { remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc4").val(); } } } }, "loc5": { remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc5").val(); } } } } }, messages: { "loc1": { required: "Start/End Location is a required field.", remote: "Please enter a valid address." }, "loc2": { required: "Please enter at least 3 addresses.", remote: "Please enter a valid address." }, "loc3": { required: "Please enter at least 3 addresses.", remote: "Please enter a valid address." }, "loc4": { remote: "Please enter a valid address." }, "loc5": { remote: "Please enter a valid address." } } }); });
</script>
Or using the .rules("add") method:
<script src="../../Scripts/jquery.validate.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () { $("#ViewResult").validate({ onfocusout: false, onkeyup: false }); $("#loc1").rules("add", { required: true, remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc1").val(); } } }, messages: { required: "Start/End Location is a required field.", remote: "Please enter a valid address." } }); $("#loc2").rules("add", { required: true, remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc2").val(); } } }, messages: { required: "Please enter at least 3 addresses.", remote: "Please enter a valid address." } }); $("#loc3").rules("add", { required: true, remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc3").val(); } } }, messages: { required: "Please enter at least 3 addresses.", remote: "Please enter a valid address." } }); $("#loc4").rules("add", { remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc4").val(); } } }, messages: { remote: "Please enter a valid address." } }); $("#loc5").rules("add", { remote: { url: "/Home/IsValidAddress", timeout: 2000, type: "post", data: { address: function () { return $("#loc5").val(); } } }, messages: { remote: "Please enter a valid address." } }); });
</script>
来源:https://stackoverflow.com/questions/10126935/remote-jquery-validation-with-mvc-4-dynamically-validate-all-inputs-starting-wi