remote jQuery validation with MVC 4, dynamically validate all inputs starting with loc?

独自空忆成欢 提交于 2019-12-08 03:41:35

问题


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.

  1. How can I write the jQuery shorthand to create a validation rule for all textboxes starting with "loc"?
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!