Wednesday, 13 February 2019

DotnetCore Web API model validation message from resource file.

It's so simple you just need to add resource file ValidationMessage.resx under the project as I have added. After adding it you will found that corresponding ValidationMessage.Designer.resx is not available inside resource folder.


So you need to set Custom Tool property for the .resx file as ResXFileCodeGenerator, as soon as we add it, will find ValidationMessage.Designer.resx.


After enabling it and writing appropriate model with validation attribute with ErrorMessageResourceName = "Password", ErrorMessageResourceType = typeof(ValidationMessage) you may found your required 
ModelValidationState Error message from your resource file.


using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using CoreApp.WebApi.Resources;
 
namespace CoreApp.WebApi.Models
{
    public class UserLogin
    {
        [DisplayName("LoginId")]
        public int UserId { getset; }
 
        [Required(ErrorMessageResourceName = "Password", ErrorMessageResourceType = typeof(ValidationMessage)), MinLength(4), MaxLength(10)]
        public string Password { getset; }
        public DateTime? RequestTime { getset; }
 
    }
}



Note:
Personally I fall in a situation in which I was using services.AddMvcCore() and with this model validation with  DataAnnotations was not working. So after searching out found that we need to use
services.AddDataAnnotations() Extensions in order to enable DataAnnotaions validation. And that worked for DotNetCore Web API model validations.

services.AddMvcCore().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonFormatters()
.AddDataAnnotations()
.AddXmlSerializerFormatters();

Thursday, 7 February 2019

Custom Model Validation Response Globally in DotNetCore

We can validate model globally and can can have custom response globally by using ActionFilter where we can just validate context.ModelState.IsValid or not and based on that we can have custom response there. The advantage of using this filter is that we can set it for few controllers where as if we looking for to apply globally for each controller in dotnet core, now we can change the ApiBehavior using ApiBehaviorOptions. The below code is for creation for extension of IServiceCollection and then simple use inside ConfigureServices();

services.UseCoreAppCustomModelValidation();

Extension:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
 
namespace CoreApp.ModelStateValidation
{
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection UseCoreAppCustomModelValidation(this IServiceCollection services)
        {
            _ = services.Configure((Action<ApiBehaviorOptions>)(apiBehaviorOptions =>
                    apiBehaviorOptions.InvalidModelStateResponseFactory = actionContext =>
                    {
                        var message = GetModelStateErrorWithException(actionContext);
 
                        return new BadRequestObjectResult(new
                        {
                            Code = 400,
                            Status = 0,
                            Messages = message
                        });
                    }));
            return services;
        }
 
        private static ExpandoObject GetModelStateFriendlyError(ActionContext actionContext)
        {
            var modelType = actionContext.ActionDescriptor.Parameters.FirstOrDefault()?.ParameterType; //Get model type  
                                                                                                       //p => p.BindingInfo.BindingSource.Id.Equals("Body", StringComparison.InvariantCultureIgnoreCase)
 
            var expandoObj = new ExpandoObject();
            var expandoObjCollection = (ICollection<KeyValuePair<stringobject>>)expandoObj//Cannot convert IEnumrable to ExpandoObject  
 
            var dictionary = actionContext.ModelState.ToDictionary(k => k.Key, v => v.Value)
                .Where(v => v.Value.ValidationState == ModelValidationState.Invalid)
                .ToDictionary(
                k =>
                {
                    if (modelType != null)
                    {
                        var property = modelType.GetProperties().FirstOrDefault(p => p.Name.Equals(k.Key, StringComparison.InvariantCultureIgnoreCase));
                        if (property != null)
                        {
                            //Try to get the attribute  
                            var displayName = property.GetCustomAttributes(typeof(DisplayNameAttribute), true).Cast<DisplayNameAttribute>().SingleOrDefault()?.DisplayName;
                            return displayName ?? property.Name;
                        }
                    }
                    return k.Key; //Nothing found, return original validation key  
                },
                v => v.Value.Errors.Select(e => e.ErrorMessage).ToList() as object); //Box String collection
 
            foreach (var keyValuePair in dictionary)
            {
                expandoObjCollection.Add(keyValuePair);
            }
 
            return expandoObj;
        }
 
        private static List<stringGetModelStateErrorWithException(ActionContext actionContext)
        {
            List<stringerrorMessages = new List<string>();
            foreach (var error in actionContext.ModelState)
            {
                string message = error.Value.Errors != null && error.Value.Errors.Count() > 0 ?
                                    error.Value.Errors[0].Exception != null ?
                                            error.Key + " : " + error.Value.Errors[0].Exception.Message   //More weight-age is given to exception, so in case of one, use the exception message
                                    : error.Value.Errors[0].ErrorMessage != null ?
                                            error.Key + " : " + error.Value.Errors[0].ErrorMessage //Otherwise use error message
                                    : string.Empty
                            : string.Empty;
 
                if (!string.IsNullOrWhiteSpace(message))
                {
                    errorMessages.Add(message);
                }
            }
            return errorMessages;
        }
 
        private static List<stringGetModelStateError(ActionContext actionContext)
        {
            return actionContext.ModelState.Values.SelectMany(x => x.Errors)
                            .Select(x => x.ErrorMessage).ToList();
        }
    }
}

Monday, 4 February 2019

Express module in React.Js

How to install modules in Node.Js?
Either through wizard or from package.json we can add wanted modules in node.js project. I have done it through wizard and you may get reflation in package.json.




Package.json
"devDependencies": {
    "@types/node""^8.0.14",
    "express""^4.16.4"
  }


What is Express modules in Node.Js?
It use connect middle-ware that interact with core http module. So either we work with http module or can have express module in application that help us to configure endpoint, route and more rapidly. More about express could be found here .


How to use express module in node.js?
We just need to add module in project and then can call it in anywhere, like I have use in server.ts.

//load installed module 'express'.
var express = require('express');
 
//initialized express and stored in a variable app.
var app = express();
 
//Created a key having name 'port' with default process value.
app.set('port', process.env.PORT || 1337);
 
 
//Created rout for root '/'
app.get('/'function (req, res) {
    res.send('<html><body><h1>Hello World</h1></body></html>');
});
 
 
 
//Created rout for root '/about'
app.get('/about'function (req, res) {
    res.send('<html><body>My name is raj.</body></html>');
});
 
 
//We can have different verbs like get, post, delete and more.
app.post('/postdata'function (req, res) {
    res.send('POST Request');
});
 
app.put('/updatedata'function (req, res) {
    res.send('PUT Request');
});
 
 
app.delete('/deletedata'function (req, res) {
    res.send('DELETE Request');
});
 
//Again instead of http.createServer module we use app.listen to configure endpoint of App.
var server = app.listen(app.get('port'), function () {
    console.log('Node server is running..');
});



Output in browser:
For root '/'


And for '/about'




Create empty ReactJs Application in Visual Studio

Make sure you have Node.Js component installed for Visual Studio

How to verify Node.Js installed for Visual Studio or not?
Go to Windows > Visual Studio Installer > Modify > Verify Node.Js development




Just few clicks now and your first VS React Application is ready with initial template.


Server.ts
Vital gateway of project that allow us to configure listening port and end point for the project. It is typescript file having extension .ts. Let's have look on each line with comment.

//common es6 syntax to load object(http) from installed module(http).
import http = require('http');

//define port, default port for Node.Js project is 1337 that we can change.
var port = process.env.port || 1337;

//A method of http that we use to create server instance for project. Each request/response will be coming/server through (req,res)
http.createServer(function (req, res) {
    // set response header
    res.writeHead(200, { 'Content-Type''text/html' });
    // set response content    
    res.write('<html><body><h1>Hello World</h1></body></html>');
    res.end();
}).listen(port);

Output



Notes:

Details es6 syntax could be found here
https://codeburst.io/es6-tutorial-for-beginners-5f3c4e7960be
https://www.tutorialspoint.com/es6/es6_syntax.htm

Mode Core module like (http, url, path, fs, util and querystring) could be found here
https://www.tutorialsteacher.com/nodejs/nodejs-modules

Starting with React.Js

Node.Js: Is an open-source server side run-time environment that allow to run JavaScript code on server. Details info could be found here.
Official: https://nodejs.org
W3school: https://www.w3schools.com/nodejs/default.asp


React.Js: Is a client end library written by Facebook that allow us to develop app. It use NodeJs platform to work on both client and server end.

ReactJs Environment Setup
Software: Node.Js run-time, can be found here  
After installation of given component we can verify available version by using following command on CMD.

 node -v
or
 node --version




Test HelloWorld js
Create a file with simple console message.



Now open CMD with located file and run following command it will bring the output on CMD itself.
node main.js




Wednesday, 30 January 2019

How to use JWT Authorization token in swagger .netCore?

It's easy to add Swashbuckle for the DotNet core application but without any Authorization for the API.
But some time we need to pass additional Authorization header in to API call. On that time this trick worked for me.


// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1"new Info
    {
        Version = "v1",
        Title = "Core API",
        Description = "ASP.NET Core API",
        TermsOfService = "None",
        Contact = new Contact
        {
            Name = "Raj Kumar",
            Email = ""
        },
        License = new License
        {
            Name = "Demo"
        }
    });
    c.AddSecurityDefinition("Bearer"new ApiKeyScheme()
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
        Name = "Authorization",
        In = "header",
        Type = "apiKey"
    });
    c.AddSecurityRequirement(new Dictionary<stringIEnumerable<string>>
    {
    {"Bearer",new string[]{}}
    });
});

If we need to add some additional header instead of Authorization, we can add it

// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1"new Info
    {
        Version = "v1",
        Title = "Core API",
        Description = "ASP.NET Core API",
        TermsOfService = "None",
        Contact = new Contact
        {
            Name = "Raj Kumar",
            Email = ""
        },
        License = new License
        {
            Name = "Demo"
        }
    });
    c.AddSecurityDefinition("Bearer"new ApiKeyScheme()
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
        Name = "Authorization",
        In = "header",
        Type = "apiKey"
    });
    c.AddSecurityRequirement(new Dictionary<stringIEnumerable<string>>
    {
        { "Bearer"new string[] { } }
    });
 
    c.AddSecurityDefinition("AdditionaHeaderData"new ApiKeyScheme()
    {
        Description = "Based on API demand",
        Name = "AdditionaHeaderData",
        In = "header",
        Type = "apiKey"
    });
    c.AddSecurityRequirement(new Dictionary<stringIEnumerable<string>>
    {
        { "AdditionaHeaderData"new string[] { } }
    });
});


Output:

If you want to modify the UI of swagger you can do it by adding your custom js and css file. So just add files

>wwwroot
--->swagger-ui
------->custom.js
------->custom.css



app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json""API V1");
    c.RoutePrefix ="docs";
    c.InjectStylesheet("/swagger-ui/custom.css");
    c.InjectJavascript("/swagger-ui/custom.js");
 
});

Monday, 28 January 2019

How to get Enum Description, DisplayName and Dictionary?

I was using it frequently but missed to post it. Let's see how to create a simple Enum extension method and how to transform Enums in to list/dictionary with its DisplayName or Description attribute.

Helper:
using System;
using System.ComponentModel;
using System.Reflection;
 
namespace EnumHelper
{
    public static class EnumExtensions
    {
        public static string ToDescription(this Enum value)
        {
            FieldInfo field;
            DescriptionAttribute attribute;
            string result;
 
            field = value.GetType().GetField(value.ToString());
            attribute = (DescriptionAttribute)Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute));
            result = attribute != null ? attribute.Description : string.Empty;
 
            return result;
        }
 
        public static bool HasDescription(this Enum someEnum)
        {
            return !string.IsNullOrEmpty(someEnum.ToDescription());
        }
 
        public static string ToDisplayName(this Enum value)
        {
            FieldInfo field;
            DisplayNameAttribute attribute;
            string result;
 
            field = value.GetType().GetField(value.ToString());
            attribute = (DisplayNameAttribute)Attribute.GetCustomAttribute(field, typeof(DisplayNameAttribute));
            result = attribute != null ? attribute.DisplayName : string.Empty;
 
            return result;
        }
 
        public static bool HasDisplayName(this Enum someEnum)
        {
            return !string.IsNullOrEmpty(someEnum.ToDisplayName());
        }
 
        public static int ToValue(this Enum someEnum)
        {
            return Convert.ToInt32(someEnum);
        }
 
    }
}

Implementation:
using System;
using System.ComponentModel;
using System.Linq;
 
namespace EnumHelper
{
 
    enum PrimaryColors
    {
        [Description("R for Red")]
        [DisplayName("R")]
        Red  = 1,
 
        [Description("G for Green")]
        [DisplayName("G")]
        Green = 1,
 
 
        [Description("B for Blue")]
        [DisplayName("B")]
        Blue = 4    
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            var hasDescription = PrimaryColors.Red.HasDescription();
            var dataDescription = PrimaryColors.Red.ToDescription();
            Console.WriteLine($"hasDescription: {hasDescription}");
            Console.WriteLine($"dataDescription: {dataDescription}");
 
 
            var dataText = PrimaryColors.Red.ToString();
            Console.WriteLine($"dataText: {dataText}");
 
            var dataValue = PrimaryColors.Red.ToValue();
            Console.WriteLine($"dataValue: {dataValue}");
 
 
            var hasDIsplayName = PrimaryColors.Red.HasDisplayName();
            var dataDiaplayName = PrimaryColors.Red.ToDisplayName();
            Console.WriteLine($"hasDIsplayName: {hasDIsplayName}");
            Console.WriteLine($"dataDiaplayName: {dataDiaplayName}");
 
 
            var listText = Enum.GetValues(typeof(PrimaryColors)).Cast<PrimaryColors>().Select( d => d.ToString()).ToList();
            var listValues = Enum.GetValues(typeof(PrimaryColors)).Cast<int>().ToList();
            var dictionary_with_value_and_description = Enum.GetValues(typeof(PrimaryColors))
                            .Cast<PrimaryColors>()
                            .ToDictionary( data => data.ToValue(), data => data.ToDescription());
 
            var dictionary_with_value_and_display_name = Enum.GetValues(typeof(PrimaryColors))
                            .Cast<PrimaryColors>()
                            .ToDictionary(data => data.ToValue(), data => data.ToDisplayName());
 
 
 
            //Note: We can assign duplicate value like Red = 1, Green = 1. But having duplicate may lead error/affect resultset if we filter/parse.
 
            Console.Read();
        }
    }
}