Search This Blog

Sunday 8 December 2019

Validate nested class in MVC with Validator.TryValidateObject()

using System.ComponentModel.DataAnnotations;


public class ValidateModel
{
    static string result = string.Empty;
    public static string Validate(object obj)
    {
        var context = new ValidationContext(obj, serviceProvider: null, items: null);
        var results = new List<ValidationResult>();
        var isValid = Validator.TryValidateObject(obj, context, results, true);
        if (!isValid)
            foreach (var validationResult in results)
                result += validationResult.ErrorMessage;
        foreach (var prop in obj.GetType().GetProperties())
        {
            if (prop.PropertyType == typeof(string) || prop.PropertyType.IsValueType) continue;
            var value = prop.GetValue(obj);
            if (value == null) continue;
            var isEnumerable = value as IEnumerable;
            if (isEnumerable == null)
                Validate(value);
            else
                foreach (var nestedModel in isEnumerable)
                    Validate(nestedModel);
        }
        return result;
    }
}

Note:- 
MVC ModelBinder is doing all complex type DataAnnotations validation itself when you checked ModelState.IsValid in the action but it's failed when you pass the object instead of model.

In that case, you need to call the Validator.TryValidateObject() function but it's also failed to validate the complex/nested class DataAnnotations.

The above example is the solution for overcome to this issue using recursive function call.


=>Sample Model
public class RegistrationRequest
{
    public object body { get; set; }
}
public class Registration
{
    public int Id { get; set; }
    [Required]
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    [Required]
    public string LastName { get; set; }
    public Address address { get; set; }
    public List<PastHistory> pastHistory { get; set; }
}
public class Address
{
    [Required]
    public string Address1 { get; set; }
    [Required]
    public string Address2 { get; set; }
    public string Address3 { get; set; }
    [Required]
    public string State { get; set; }
    [Required]
    public string City { get; set; }
    [Required]
    public string Pincode { get; set; }
}
public class PastHistory
{
    [Required]
    public string ComapnyName { get; set; }
}

=>Sample Controller
[HttpPost]
public HttpResponseMessage Registration(RegistrationRequest reg)
{
    Registration registration = JsonConvert.DeserializeObject<Registration>(reg.body.ToString());

    string validateResult = ValidateModel.Validate(registration);
    if (!string.IsNullOrEmpty(validateResult))
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, validateResult);
    else
        return Request.CreateResponse(HttpStatusCode.OK);
}

=>Sample JSON
   "body":{ 
      "Id":"1",
      "FirstName":"Ram",
      "MiddleName":"",
      "LastName":"",
      "Address":{ 
         "Address1":"",
         "Address2":"",
         "Address3":"",
         "State":"",
         "City":"",
         "Pincode":""
      },
      "PastHistory":[ 
         { 
            "ComapnyName":""
         }
      ]
   }
}



How to get all Errors from modelState in ASP.Net MVC?


[HttpPost]
public HttpResponseMessage Registration(RegistrationRequest reg)
{
    if (ModelState.IsValid)
    {
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    IEnumerable<string> errors = ModelState.Values.SelectMany(v => v.Errors.Select(b => b.ErrorMessage));
    string strErrors = string.Join("; "errors);

    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, strErrors);
}


OR


[HttpPost]
public HttpResponseMessage Registration(RegistrationRequest reg)
{
    if (ModelState.IsValid)
    {
        return Request.CreateResponse(HttpStatusCode.OK);
    }

    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}

Saturday 7 December 2019

OR condition in regular expression

=>Web API
using System.ComponentModel.DataAnnotations;

[RegularExpression(@"^(Y)|(N)$", ErrorMessage = "IsHandicap can only be Y or N.")]
public string IsHandicap{ getset; }

=>C Sharp
using System.Text.RegularExpressions;


string regex = @"^(Y)|(N)$";
string inputString = "Y";
Match match = Regex.Match(inputString, regex);

=>Java Script
<script>
    function Validate() {
        var text = document.getElementById("TextBox1").value;
        var pattern = "^(Y)|(N)$";
        var result = text.match(pattern);
        if (!result)
            alert("IsHandicap can only be Y or N.");
    }
</script>

<asp:TextBox ID="TextBox1" runat="server" ClientIDMode="Static"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="return Validate();" />


Note:- Input string only valid when IsHandicap field value "Y" and "N".


[] - Find any character matching between in the square brackets.
() - Find matching character or word in the brackets.

Regular expression for mobile number with fix country code

=>Web API
using System.ComponentModel.DataAnnotations;

[RegularExpression(@"^(91)?\d{10}$", ErrorMessage = "invalid country code or mobile no.")]   
public string mobileno { getset; }

=>C Sharp

using System.Text.RegularExpressions;

string regex = @"^(91)?\d{10}$";
string inputString = "919876543210";
Match match = Regex.Match(inputString, regex);

=>Java Script
<script>
    function Validate() {
        var text = document.getElementById("TextBox1").value;
        var pattern = "^(91)?\d{10}$";
        var result = text.match(pattern);
        if (!result)
            alert("invalid country code or mobile no.");
    }
</script>

<asp:TextBox ID="TextBox1" runat="server" ClientIDMode="Static"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="return Validate();" />


Note:- Input string only valid when mobile no passed with Indian country code i.e. 91.

Saturday 30 November 2019

How to remove last comma from string in sql server


DECLARE @STRING VARCHAR(50) = 'ABC,XYZ,'

SELECT IIF(CHARINDEX(',',REVERSE(@STRING))=1,LEFT(@STRING,LEN(@STRING)-1),@STRING)

OR

SELECT CASE 
           WHEN CHARINDEX(',',REVERSE(@STRING))=
           THEN LEFT(@STRING,LEN(@STRING)-1) 
           ELSE @STRING 
       END


Wednesday 9 October 2019

Allow only one space between words in javascript

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script>
        //Way 1
        function Validate1() {
            var a = document.getElementById("TextBox1").value;
            var b = a.split(' ');
            var c = 0;
            for (var i = 0; i < b.length; i++) {
                if (b[i] == '') {
                    c++;
                    if (c == 2) {
                        document.getElementById("TextBox1").value = a.substring(0, a.length - 1);
                        return false;
                    }
                }
            }
        }
        //Way 2
        function Validate2() {
            var a = document.getElementById("TextBox2").value;
            var b = a.split(' ');
            var c = 0;
            for (var i = 0; i < b.length; i++) {
                if (b[i] == '') {
                    c++;
                    if (c == 2) {
                        alert('Only one space allowed in/between the word.');
                        document.getElementById("TextBox2").value = a.substring(0, a.length - 1);
                        return false;
                    }
                }
            }
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            Way 1 (Without Message) :-<asp:TextBox ID="TextBox1" runat="server" onkeyup="Validate1();" ClientIDMode="Static"></asp:TextBox>
            <br />
            <br />
            Way 2 (Alert With Message) :-<asp:TextBox ID="TextBox2" runat="server" onkeyup="Validate2();" ClientIDMode="Static"></asp:TextBox>
        </div>
    </form>
</body>
</html>