Remote Validation Unobtrusive using Razor Method

16 posts, 0 answers
  1. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 21 Feb Link to this post

    Dear All,

    I have just downloaded the asp.net MVC product.

    I started with the validation using DataAnnotation attributes, which works fine for client-side validation on the UI.

    I then searched for implementation of server-side validation attribute for DataAnnotation where I found the [Remote] attribute that allow to call methods on the controller, looks pretty good.

    I started with the following at the Controller:

    public JsonResult IsValidName(string coin_name_2)
            {
                bool found = db.IGL_coin.Any(name => name.coin_name_2 == coin_name_2);
                if (!found)
                {
                    return Json(true, JsonRequestBehavior.AllowGet);
                }
                return Json(false, JsonRequestBehavior.AllowGet);
            }

     

    Then I decorate my model (IGL_coin) with MetaData class that holds the validation as follows:

    // Metadata defenitions
    public class CoinMetadata
        {
            public int coin_id { get; set; }
     
            public string coin_name_1 { get; set; }
     
            [Required(ErrorMessageResourceType = typeof(Errors), ErrorMessageResourceName = "NameReq")]
            [Display(Name = "CoinName", ResourceType = typeof(ScreenRes))]
            [Remote("IsValidName", "Coin", ErrorMessageResourceType = typeof(Errors), ErrorMessageResourceName = "NameDuplicate")]
            public string coin_name_2 { get; set; }
     
            [Display(Name = "Rate", ResourceType = typeof(ScreenRes))]
            [Required(ErrorMessageResourceType = typeof(Errors), ErrorMessageResourceName = "RateReq")]
            [Range(0.00001,100000, ErrorMessageResourceType=typeof(Errors), ErrorMessageResourceName="RateInvalid")]
            public decimal coin_rate { get; set; }
        }
     
    // Partial Classes defenitions
    [MetadataType(typeof(CoinMetadata))]
    public partial class IGL_coin
    {}

     

    Then my CoinCustomEditor partial view has the following markup to show the details:

    <div style="margin: 5px 15px 5px 15px; height: auto; width: 350px">
        @using (Html.BeginForm())
         {
            @Html.AntiForgeryToken()
     
            @Html.HiddenFor(model => model.coin_id)
            @Html.ValidationSummary()
            <ul id="fieldlist">
                <li>
                    @Html.LabelFor(model => model.coin_name_2)
                    @Html.TextBoxFor(model => model.coin_name_2)
                    @*@Html.Kendo().MaskedTextBoxFor(model => model.coin_name_2).Name("coin_name_2").HtmlAttributes(new { style = "width: 100%;" })*@
                    @Html.ValidationMessageFor(model => model.coin_name_2)
     
                </li>
                <li>
                    @Html.LabelFor(model => model.coin_rate)
                    @Html.Kendo().TextBoxFor(model => model.coin_rate).Name("coin_rate").HtmlAttributes(new { style = "width: 100%;" })
                    @Html.ValidationMessageFor(model => model.coin_rate)
                </li>
            </ul>
         }
    </div>
    @Scripts.Render("~/bundles/jqueryval")

     

    This partial view is called from the add/edit action on the grid using GridEditMode.PopUp and .TemplateName("CoinCustomEditor")).

    The problem is that the remote attribute calls the method IsValidName correctly as shown by fiddler (see attached file).

    The result in the Partial view shows the red border around the TextBoxFor but the error message is not shown.

    Just in case this is the jqueryval scripts loaded by partial : @Scripts.Render("~/bundles/jqueryval"), which are defined at the _Layout as follows:

    <head>
        <title>@ViewBag.Title - My App</title>
     
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/kendo")
     
        @Styles.Render("~/Content/kendo/css")
         
        <link href="@Url.Content("~/Content/kendo/kendo.common.min.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/kendo/kendo.mobile.all.min.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/kendo/kendo.dataviz.min.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/kendo/kendo.default.min.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/kendo/kendo.dataviz.default.min.css")" rel="stylesheet" type="text/css" />
        <link href="@Url.Content("~/Content/kendo/kendo.rtl.min.css")" rel="stylesheet" type="text/css" />
     
        <script src="@Url.Content("~/Scripts/kendo/jquery.min.js")"></script>
     
        <script src="@Url.Content("~/Scripts/kendo/angular.min.js")"></script>
        <script src="@Url.Content("~/Scripts/kendo/jszip.min.js")"></script>
        <script src="@Url.Content("~/Scripts/kendo/kendo.all.min.js")"></script>
        <script src="@Url.Content("~/Scripts/kendo/kendo.aspnetmvc.min.js")"></script>
    </head>

     

    and also the BundleConfig definitions:

    public class BundleConfig
    {
        // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                            "~/Scripts/jquery-{version}.js"));
     
            //bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include("~/Scripts/jquery.validate*"));
            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate.min.js",
                        "~/Scripts/jquery.validate.unobtrusive.js"));
     
            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                            "~/Scripts/modernizr-*"));
     
            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                        "~/Scripts/bootstrap.js",
                        "~/Scripts/respond.js"));
     
            //bundles.Add(new StyleBundle("~/Content/css").Include(
            //          "~/Content/bootstrap.css",
            //          "~/Content/Site.css"));
     
            bundles.Add(new ScriptBundle("~/bundles/kendo").Include(
                     "~/Scripts/kendo/2016.2.504/kendo.all.min.js",
                // "~/Scripts/kendo/kendo.timezones.min.js", // uncomment if using the Scheduler
                     "~/Scripts/kendo/2016.2.504/kendo.aspnetmvc.min.js"));
     
            //bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
            //       "~/Content/kendo/2016.2.504/kendo.common-bootstrap.min.css",
            //       "~/Content/kendo/2016.2.504/kendo.bootstrap.min.css"));
     
            bundles.IgnoreList.Clear();
     
            bundles.Add(new StyleBundle("~/Content/kendo/css").Include(
                "~/Content/kendo/2016.2.504/kendo.common.min.css",
                "~/Content/kendo/2016.2.504/kendo.default.min.css"));
     
     
        }
    }

     

    I hope to find some help, as server-side validation is crucial to go further.

    Best

  2. Ianko
    Admin
    Ianko avatar
    1720 posts

    Posted 23 Feb Link to this post

    Hello Yassen,

    If I understand correctly, the problem is with the @Html.TextBoxFor(model => model.coin_name_2) part. This TextBoxFor is not a component from the UI for ASP.NET MVC suite, but the native MVC extensions for a textbox input. Using the basic MVC extensions and the jQuery unobtrusive validation are not components anyhow controlled by the components we provide. 

    On a side note, the TextBoxFor renders a plain <input/> tag without any decoration at all. Therefore, you could easily examine the HTML and CSS rendered and see why the message is not printed. 

    If, however, this is indeed related to Kendo UI or UI for ASP.NET MVC somehow, please provide a simple, locally runnable sample that demonstrates the case you have so that I can have a better look at the scenario and debug output of this code. 

    Regards,
    Ianko
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  3. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 23 Feb in reply to Ianko Link to this post

    Thank Lanko,

    as a matter of fact if I use Kendo as follows:

    @Html.Kendo().MaskedTextBoxFor(model => model.coin_name_2).Name("coin_name_2").HtmlAttributes(new { style = "width: 100%;" })

    No error message is displayed neither the red border.

    Regards

  4. Ianko
    Admin
    Ianko avatar
    1720 posts

    Posted 24 Feb Link to this post

    Hello Yassen,

    I created a sample project with MaskedTextBoxFor and unobtrusive jQuery validation, where everything seems to be in order. You can find attached the sample project.

    On a side note, even with a plain TextBoxFor, the validation message shows up fine.

    Regards,
    Ianko
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  5. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 26 Feb in reply to Ianko Link to this post

    Dear Lanko,

    Thanks for the running project, unfortunately I could not fix mine according to yours.

    Could you please have a look at the attached sample project to see what is causing the problem?

    Try to add new record with coin_name = error.

    Appreciate your feedback.

  6. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 26 Feb in reply to Yassen Link to this post

    Hello Lanko,

    I have found that If I copy the "CoinCustomEditor" content to the home page and add the following to the home controller the validation works.

    public ActionResult Index ()
    {
        return View(new IGL_coin() );
    }

     

  7. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 27 Feb Link to this post

    Thanks Lanko, I have found this doc http://demos.telerik.com/aspnet-mvc/grid/editing-remote-validation very helpfull
  8. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 10 Mar in reply to Ianko Link to this post

    Hello Lanko,

    I am terribly sorry for coming back with bad news.

    the validation works for the first time only, if I insists to save the data in error for a second time it passes and get saved !!

    Can you help me on this ???

  9. Ianko
    Admin
    Ianko avatar
    1720 posts

    Posted 13 Mar Link to this post

    Hello Yassen,

    I tested the same using the demo you linked (http://demos.telerik.com/aspnet-mvc/grid/editing-remote-validation), but I was unable to reproduce the described behavior. Validation prevents updates every time when validation fails. 

    Regards,
    Ianko
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  10. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 16 Mar in reply to Ianko Link to this post

    Dear Lanko,

    I am afraid it is not true. lease have a look at the attached file, as it shows a record of the demo from your site.

    Best regards

  11. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 16 Mar in reply to Ianko Link to this post

    Dear Lanko,

    I am afraid it is not true. Please have a look at the attached recording of the demo at your site.

    regards

  12. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 16 Mar in reply to Yassen Link to this post

    Sorry for multiple posts,

    Here is the recording

  13. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 16 Mar in reply to Yassen Link to this post

    Sorry for multiple posts,

    Here is the recording

  14. Ianko
    Admin
    Ianko avatar
    1720 posts

    Posted 17 Mar Link to this post

    Hello Yassen,

    The described behavior indeed happens and I can agree with you that it is strange. 

    The reason for that behavior is that the idea of the remote validation is initially designed to work with a Form (https://msdn.microsoft.com/en-us/library/gg508808(vs.98).aspx). With Kendo Grid and Kendo DataSource, however, the submission cannot be stopped during the AJAX request. One option would be to make the remote validation synchronous, but jQuery dropped the async: false support. 

    Typically, the scenario illustrated with the demo, is a pure hint on how remote validation would be used in Kendo Grid. In a real-life situation, however, you will need a server validation plus the client-side remote validation for the model update to work as expected. 

    I hope that clarifies further the situation and the case.

    Regards,
    Ianko
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
  15. Yassen
    Yassen avatar
    22 posts
    Member since:
    Oct 2016

    Posted 17 Mar in reply to Ianko Link to this post

    Hello Lanko,

    I know that server validation is not a option, but your answer is kind of frustrating to me.

    I am evaluating the use of your controls in our app, this kind of validation is crucial to have a definite answer to go or not

    Thanks

  16. Ianko
    Admin
    Ianko avatar
    1720 posts

    Posted 20 Mar Link to this post

    Hello Yassen,

    Let me explain a bit further and try to clarify things with remote validation. 

    Generally, remote validation is a feature of MVC provided by Microsoft with the conjunction of the jquery-validation library. Kendo Grid and Kendo Validator does not offer support for that out of the box. Such a functionality cannot be introduced as a built-in feature because jquery-validation does not offer validation over asynchronous submissions, like the one Kendo Grid does to update rows. This is why, the commonly known remote validation works only with forms. 

    The demo we provide is intended to only show how to possibly implement a remote validation-like functionality with Kendo Validator and Grid by utilizing the data attributes that MVC generates for the fields.  The code shown in the demo is far from a complete solution and you should consider that only as a hint and guidance of such a feature implemented. That means that further application requirements should be accomplished by implementing code that satisfies the needs of the application. 

    Due to the asynchronous nature of the implemented remote validation, there is no possible way to program a validation rule that can interact with the row submission and cancel it. 

    You could possibly implement logic that would disable the button, however, the solution should be accompanied by custom code, which is related to application development and logic.

    Plus, common best practices regarding validation is to have both client and server validation. Having a server validation for the same client-side validation rule would prevent model update or create and return an error to the grid.

    Regards,
    Ianko
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top