‘<‘ is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.


If you are getting this error message with Web API in Blazor WeAssembly application. You can troubleshoot following ways.

  1. Take the api end point and trigger with PostMan
  2. If it is not triggering, then try to see the api method attribute. So many we missed out input parameter of Web api method.

In my case, I was missed out InstanceId for Web API Method

 [HttpGet]
 [Route("[action]]
 public async Task<List<ProductModel>> GetProducts(int instanceId) => await _service.GetProducts(instanceId);

Fix: Pass the instanceId parameter to web api method.

 [HttpGet]
 [Route("[action]/{instanceId}")]
 public async Task<List<ProductModel>> GetProducts(int instanceId) => await _service.GetProducts(instanceId);

What is API Gateway in Asp.net Core Micro Service?


In ASP.NET Core microservices architecture, an API Gateway acts as a central entry point for client applications to access various microservices. It provides a single unified interface for clients to interact with multiple services.

The API Gateway handles requests from clients, performs necessary routing and protocol translation, and dispatches those requests to the appropriate microservices.

Here are some key features and benefits of using API Gateways in ASP.NET Core microservices:

Request aggregation: An API Gateway can aggregate multiple requests from clients into a single request to reduce chattiness between clients and microservices. This helps improve performance and reduce network overhead.

Routing and load balancing: The API Gateway can handle routing requests to different microservices based on the requested resource or operation. It can also perform load balancing to distribute the incoming traffic across multiple instances of microservices.

Protocol translation: Clients may use different protocols or data formats than what the microservices support. The API Gateway can handle the translation of protocols (e.g., HTTP to gRPC) and data formats (e.g., JSON to Protobuf), ensuring seamless communication between clients and microservices.

Authentication and authorization: The API Gateway can handle authentication and authorization for incoming requests. It can enforce security policies, authenticate client requests, and authorize access to specific microservices based on the client’s identity and permissions.

Caching and rate limiting: API Gateways can implement caching mechanisms to improve performance by serving cached responses for repeated requests. They can also enforce rate limits to prevent abuse and protect microservices from excessive traffic.

Logging and monitoring: API Gateways can log incoming requests and responses, providing valuable insights into the system’s behavior. They can also integrate with monitoring tools to collect metrics and perform health checks on microservices.

There are so many api gateways which can we use in asp.net core microservice. like Ocelot, Azure API Management, AWS API Gateway, Kong etc

In this demo we will see basic demo of Ocelot.

Step 1: Create the 3 project layers using Asp.net Core for StudentService, TeacherService and Gateways layer

Step 2: Go to Ocelot gateway layer and installed the ocelot NuGet package.

Step 3: Create Ocelot.json file and configure the routing using Upstream and Downstream like this

{
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5003"
  },
  "Routes": [
    {
      "UpstreamPathTemplate": "/gateway/students",
      "UpstreamHttpMethod": [ "Get" ],
      "DownstreamPathTemplate": "/api/student",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5001
        }
      ]
    },
    {
      "UpstreamPathTemplate": "/gateway/students/{Id}",
      "UpstreamHttpMethod": [ "Get" ],
      "DownstreamPathTemplate": "/api/student/{Id}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5001
        }
      ]
    },
    {
      "UpstreamPathTemplate": "/gateway/teachers",
      "UpstreamHttpMethod": [ "Get" ],
      "DownstreamPathTemplate": "/api/teacher",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5002
        }
      ]
    },
    {
      "UpstreamPathTemplate": "/gateway/teacher/{Id}",
      "UpstreamHttpMethod": [ "Get" ],
      "DownstreamPathTemplate": "/api/teachers/{Id}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5002
        }
      ]
    }
  ]
}

This is main setting configuration file, which will read the input request and route to specific project api Countroller URL.

If you will give

http://localhost:5003/gateway/students

Then It will Call http://localhost:5001/api/student

Again If you type http://localhost:5003/gateway/teachers

It will route to http://localhost:5002/api/teacher

In the above setting we are seeing with use of single api endpoint http://localhost:5003/

we are calling multiple microservice api endpoints.

Step 4: Go to the program file of OcelotGateway project and configure the middleware pipeline like this

using Ocelot.DependencyInjection;
using Ocelot.Middleware;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();


builder.Configuration.AddJsonFile("ocelot.json",optional:false,reloadOnChange:true);
builder.Services.AddOcelot(builder.Configuration);
var app = builder.Build();


app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

await app.UseOcelot();

app.Run();

Step 5: Give some dummy data in Student and Teacher We API Controller

Step 6: Make all 3-project layer as Starup project layer.

Step 7: Run the application and test it.

Source code to Download: https://github.com/Chandradev819/Ocelot_API_Gateway_Demo

Creating Serverless Microservices with AWS Lambda and ASP.NET Core


As you know Micro service is one alternative approach to write Web API method. There are so many ways to create the micro-service. But in this post i m going to write creating micro service using Amazon Web Service(AWS) Lambda ToolKit on Asp.net Core

what is the Serverless Microservices ?

Serverless microservices are deployed within a serverless vendor’s infrastructure and only run when they are needed by the application. Depending on the size of a microservice, it may also be broken up into even smaller functions.

It doesn’t means that there will be no server. There will be cloud vendor’s server.

AWS use the Lamda and API gateways for this functionalities.

What are the advantages of this approach ?

1. You don’t have to pay for idle server time. So it will save huge deployment cost
2. If you have small application like POC and you are going to use that application for specific time interval then this approach will good. It will save huge money.
3. On demand we can scale the application, since it is on cloud.
4. It is give good performance as compare to monolithic approach.

How to create Serverless microservice with AWS

Step 1: Install the AWS Toolkit Extension as given below

Step 2: Create the Web Api Serverless Project like this

This template will add the all the requited dll and required files for us to making serverless microservice

Step 3: Add some Empty API controller in Controller folder and write some test method like this



using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Net.Http;

namespace AWSServerless3.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        // GET: api/Test
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "This is from Test Controller" };
        }
        //external
        [HttpGet]
        [Route("external")]
        public string External()
        {
            try
            {
                HttpClient client = new HttpClient();
                var requestTask = client.GetStringAsync("http://www.chandradev819.wordpress.com");
                requestTask.Wait();
                return "external connectivity PASS";
            }
            catch (Exception e)
            {
                return "external connectivity FAIL";
            }
        }


    }
}

Add one more controller i.e EmpController



using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace AWSServerless3.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmpController : ControllerBase
    {
        // GET: api/Emp
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "This is from Emp Controller" };
        }
    }
}

Step 4; Build the application and run on local machine before deployment

Now We are good to deploy on AWS. Now we have to create the profile on

https://aws.amazon.com/

Configure AWS user credentials as given below post

https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/credentials.html

Step 5: After successfully configure, Right click on Solution explores and deploy the application like this

Now publish the application on AWS Cloud like this

After published we will get the URL like this

Now our services has been deployed as Server less microservice on AWS Cloud. We donot have to do any thing.

Now we are ready to use the microservice on our application

Summary

I hope in this small post you might have got clear idea about creating Serverless Microservice using AWS Lambda Toolkit in Asp.net Core application.

Creating Web Api Core 3.0 layer using Dapper and .net standard 2.0


Recently I got a chance to work with dapper using .net standard 2.0 So i thought to write my learning with you in this small blog post.

Firstly we will know what is the dapper ?

Dapper is micro ORM(Object Relational Mapper) framework which helps to map database directly with C# object. It is developed by StackOverflow team and released as open source.

Advantages of Dapper

1. It is a high-performance data access system
2. It is database independent
3. Same code work with all relational database.
4. Fewer lines of code.
5. Easy Handling of SQL Query.
6. Easy Handling of Stored Procedure.
7. Dapper also allows fetching multiple data based on multiple inputs.
8. Get generic result for simple or complex data type.
9. ease of use
10. It provides support for both static and dynamic object binding using transactions, stored
procedures, or bulk inserts of data.

In this post I have also used .net standard 2.0, so we have to know what is the advantage of this

Advantages of .net standard 2.0

>> Same code can be shared on all type of .net application. This will be portable. This means you can write and can use in applications that run on multiple platforms. Their purpose is to share code between applications.

Now we will see how to implement in asp.net core web api

In this demo I m going to design the simple demo web api as given below simple architecture

Step 1: Now we will Create the blank empty web api project like this

Step 2: Right click on solution explorer and create the EmpManagement.Entities layers using .net standard 2.0 like this

Step 3: Follow the same steps and create the EmpManagement.Repository

Step 4: Follow the same steps and create the EmpManagement.Repository.Interfaces

Step 5: Create the table and sp in database like this

USE [EmpManagement]
GO
/****** Object:  StoredProcedure [dbo].[AddEmp]    Script Date: 12/12/2019 10:14:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[AddEmp]
   @EmpName nvarchar(50),  
    @EmpAddress nvarchar(50),  
    @EmailId nvarchar(50),  
    @MobileNum nvarchar(50)  
   
AS  
 
BEGIN  
SET NOCOUNT ON;  
insert into tblEmp(EmpName, EmpAddress, EmailId, MobileNum)  
      values(@EmpName, @EmpAddress, @EmailId, @MobileNum)  
END  

GO
/****** Object:  StoredProcedure [dbo].[DeleteEmp]    Script Date: 12/12/2019 10:14:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[DeleteEmp]
   @Id int
   
AS  
 
BEGIN  
SET NOCOUNT ON;  
DELETE from tblEmp where	Id=@Id 
END  

GO
/****** Object:  StoredProcedure [dbo].[GetAllEmps]    Script Date: 12/12/2019 10:14:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetAllEmps]
  
   
AS  
 
BEGIN  
SET NOCOUNT ON;  
SELECT * from TBLEMP
END  

GO
/****** Object:  StoredProcedure [dbo].[GetEmpById]    Script Date: 12/12/2019 10:14:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetEmpById]
  @Id int
   
AS  
 
BEGIN  
SET NOCOUNT ON;  
SELECT * from TBLEMP where Id=@Id
END  

GO
/****** Object:  StoredProcedure [dbo].[UpdateEmp]    Script Date: 12/12/2019 10:14:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[UpdateEmp]
  @Id int,
  @EmpName nvarchar(50),
  @EmpAddress nvarchar(50),
  @EmailId nvarchar(50),
  @MobileNum nvarchar(50)

AS  
BEGIN  
SET NOCOUNT ON;  
UPDATE tblEmp SET EmpName=@EmpName,EmpAddress=@EmpAddress,EmailId=@EmailId,MobileNum=@MobileNum where Id=@Id	 
END  

GO
/****** Object:  Table [dbo].[tblEmp]    Script Date: 12/12/2019 10:14:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tblEmp](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[EmpName] [nvarchar](50) NULL,
	[EmpAddress] [nvarchar](50) NULL,
	[EmailId] [nvarchar](50) NULL,
	[MobileNum] [nvarchar](50) NULL,
 CONSTRAINT [PK_tblEmp] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

Step 6: Go to EmpManagement.Entities layer and Create the Emp Entities class like this

using System;

namespace DataManagement.Entities
{
    public class Emp
    {
        public int Id { get; set; }
        public string EmpName { get; set; }
        public string EmpAddress { get; set; }
        public string EmailId { get; set; }
        public string MobileNum { get; set; }
    }
}

Step 7: Go to EmpManagement.Repository.Interfaces layer and Create the generic interface like this

using System.Collections.Generic;

namespace DataManagement.Repository.Interfaces
{

    public interface IEmpRepository<T> where T : class
    {
        IEnumerable<T> GetAllEmp();
        T GetEmpById(int id);
        void AddEmp(T entity);
        void DeleteEmp(int id);
        void UpdateEmp(T entity);
    }


}

Step 8: Create the BaseRepository.cs file in EmpManagement.Repository layer like this

using System;
using System.Data;
using System.Data.SqlClient;

namespace DataManagement.Repository
{
    public class BaseRepository : IDisposable
    {
        protected IDbConnection con;
        public BaseRepository()
        {
            string connectionString = "Data Source=localhost;Initial Catalog=EmpManagement;Integrated Security=True";
            con = new SqlConnection(connectionString);
        }
        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}

Step 9: Create the BaseRepository.cs file in EmpManagement.Repository layer like this

using Dapper;
using DataManagement.Entities;
using DataManagement.Repository;
using DataManagement.Repository.Interfaces;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace EmpManagement.Repository
{
    public  class EmpRepository<T> : BaseRepository, IEmpRepository<Emp>
    {
        public void AddEmp(Emp objEmp)
        {
            try
            {
                DynamicParameters parameters = new DynamicParameters();
                con.Open();
                parameters.Add("EmpName", objEmp.EmpName);
                parameters.Add("EmpAddress", objEmp.EmpAddress);
                parameters.Add("EmailId", objEmp.EmailId);
                parameters.Add("MobileNum", objEmp.MobileNum);
                SqlMapper.Execute(con, "AddEmp", param: parameters, commandType: CommandType.StoredProcedure);

                //For implementing commandtimeout and transaction
                // SqlMapper.Execute(con, "AddEmp", param: parameters, transaction:null, commandTimeout: 100, commandType: CommandType.StoredProcedure);
                // Other approach to excecute Storeprocedure in dapper
                // con.Execute("AddEmp", parameters, null, null, commandType: CommandType.StoredProcedure);

            }
            catch (Exception ex)
            {

                throw ex;
            }
        }

        public void DeleteEmp(int Id)
        {
            try
            {
                DynamicParameters parameters = new DynamicParameters();
                parameters.Add("Id", Id);
                SqlMapper.Execute(con, "DeleteEmp", param: parameters, commandType: CommandType.StoredProcedure);
            }
            catch (Exception)
            {

                throw;
            }
        }

        public IEnumerable<Emp> GetAllEmp()
        {
            try
            {
                return SqlMapper.Query<Emp>(con, "GetAllEmps", commandType: CommandType.StoredProcedure);
            }
            catch (Exception)
            {

                throw;
            }
        }

        public Emp GetEmpById(int Id)
        {
            try
            {
                DynamicParameters parameters = new DynamicParameters();
                parameters.Add("Id", Id);
                return SqlMapper.Query<Emp>(con, "GetEmpById", parameters, commandType: CommandType.StoredProcedure).FirstOrDefault();
            }
            catch (Exception)
            {
                throw;
            }
        }

        public void UpdateEmp(Emp objEmp)
        {
            try
            {
                DynamicParameters parameters = new DynamicParameters();
                con.Open();
                parameters.Add("EmpName", objEmp.EmpName);
                parameters.Add("EmpAddress", objEmp.EmpAddress);
                parameters.Add("EmailId", objEmp.EmailId);
                parameters.Add("MobileNum", objEmp.MobileNum);
                parameters.Add("Id", objEmp.Id);
                SqlMapper.Execute(con, "UpdateEmp", param: parameters, commandType: CommandType.StoredProcedure);
            }
            catch (Exception)
            {

                throw;
            }

        }
    }
}

Step 10 :Create the Emp Controller in WebApi Layer as given below

using DataManagement.Entities;
using DataManagement.Repository.Interfaces;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace Dapper_Demo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmpController : ControllerBase
    {
      
        IEmpRepository<Emp> _empRepository;
        public EmpController(IEmpRepository<Emp> empRepository)

        {
            _empRepository = empRepository;
        }

        // GET: api/Emp
        [HttpGet]
        public IEnumerable<Emp> Get()
        {
            return _empRepository.GetAllEmp();
        }

        // GET: api/Emp/5
        [HttpGet("{id}", Name = "Get")]
        public Emp Get(int id)
        {
            return _empRepository.GetEmpById(id);
        }

        // POST: api/Emp
        [HttpPost]
        public void Post([FromBody] Emp emp)
        {
            _empRepository.AddEmp(emp);
        }

        // PUT: api/Emp/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody] Emp emp)
        {
            _empRepository.UpdateEmp(emp);
        }

        // DELETE: api/ApiWithActions/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
            _empRepository.DeleteEmp(id);
        }
    }
}

Step 11: Register the interface in Startup.cs file like this

Step 12: Now run the application you will see the output like this

Summary:

In this post we learnt that how to create the web api core standalone layer using dapper and .net standard 2.0.
You can download the working code from this github repo

Source code download from github

How to enable cross domain Ajax call in asp.net Web API 2.0 ? (Part 10)


If we have created the Web API service and we are going to consume the service in same application then we will not get any exception. But the same service if we are going to call the other application, we will get the exception

No ‘Access-Control-Allow-Origin’ header is present on the requested resource

To fix this issue we have to make the cross domain enable ajax call in our service

It is very simple to implement this functionality

Step 1: Install the Microsoft.AspNet.WebApi.Cors plugin from Nuget package manager

Step 2: Go to WebApiConfig file and the code like this

Step 3: Now you can write the ajax call to consume the service as similar as previous post

How to consume web api using Jquery