Sunday, 2 May 2021

Asp.Net Core : How to check route metadata, endpoint details?

 

To Check route metadata, you can use the following code and debug it.

app.Use(async (context, next) =>
{
 var endPoint = context.GetEndpoint();
 var routes = context.Request.RouteValues;
});

Wednesday, 31 March 2021

Responsibility of asp.net core mvc controller

 

Controller class has responsibility to respond incoming request URL by invoking appropriate action method. Controller chooses appropriate model or retrieves data from data source and passes this data to appropriate View template which generates HTML, controller sends this html response back to the caller/ user.

In other words, controller invokes appropriate action from requested URL, selects/generates data and sends this data to view, view renders data and generates appropriate HTML and Controller sends response back to the client.

Thursday, 25 March 2021

What is an Http endpoint ?

 

In simple words, It's a URL in a web application/Api like ("https://www.mysite.com/home"  or "https://localhost:5001/Account/index" ).

Basically it's a combination of 

  •                 Network protocol (like http/https, etc.).
  •                 Server address and port (like localhost:5001, etc.)
  •                 URI (to uniquely identify a resource like account/index, etc.)


Friday, 10 April 2020

ASP.NET CORE : Version specific swagger document for Web Api Core [ using asp.net core 3.0 ]


Objective : We have versioned our Web APi and want to create swagger /OpenAPI documentation version specific. i.e. when user will select specific version he would be able to see api specific to selected version.

Versioning for API is easy using ASP.NET core's inbuilt middle ware. I have created a separate post related to API versioning. This post is specific to creation of version specific swagger document.

Nuget Packages : below are the list of Nuget packages needed to implement versioning and Swagger documentation in the application.

Microsoft.AspNetCore.Mvc.Version : To implement versioning.

Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer: Used by swagger to generate version specific document.

Swashbuckle.AspNetCore.Swagger : Swagger middleware exposes json endpoint.

Swashbuckle.AspNetCore.SwaggerGen : Generates JSON file

Swashbuckle.AspNetCore.SwaggerUI : Generates interactive UI documentation for API.

Now, we will see code which we have to add in ConfigureServices and Configure methods:

Need  to add below services to implement inbuilt versioning functionality:

            services.AddApiVersioning(o =>
            {
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = new ApiVersion(1, 0);
            });   // inbuilt versioning implementation

            services.AddVersionedApiExplorer(); // swagger versioning specific

// above code is required to implement versioning. below code is required for swagger documentation.

services.AddSwaggerGen(
    options =>
    {
                    
        var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
        // add a swagger document for each discovered API version
        foreach (var description in provider.ApiVersionDescriptions)
        {
            options.SwaggerDoc(description.GroupName, new OpenApiInfo { Version = description.ApiVersion.ToString(),
                                                                        Description ="Sample API version: "+ description.GroupName ,
                                                                        Title="API Versioning Sample"
                                                                      });
        }
        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        Console.WriteLine("***************************** " + xmlPath);
        options.IncludeXmlComments(xmlPath);
    });

We need to add below code in Configure method to enable swagger documentation :

  app.UseSwagger();
            app.UseSwaggerUI(
                options =>
                {
                    var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();
                    foreach (var description in provider.ApiVersionDescriptions)
                    {
                        options.SwaggerEndpoint( $"/swagger/{description.GroupName}/swagger.json",description.GroupName.ToUpperInvariant());
                    }
                });

Now we have to add APIVersion Attribute on Controller /Action methods. like :

    /// <summary>
    /// this is sample api for version 1.0
    /// </summary>
    [ApiVersion("1.0")]
    [ApiController]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class EmployeeController : ControllerBase
    {
        /// <summary>
        /// Get api for version 1.0
        /// </summary>
        [HttpGet]
        public IActionResult Get()
        {
            return Ok(" Hello from v1");
        }
    }
 
    /// <summary>
    /// this is sample api for version 2.0
    /// </summary>
    [ApiVersion("2.0")]
    [ApiController]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class Employee2Controller : ControllerBase
    { /// <summary>
      /// Get api for version 2.0
      /// </summary>
      ///
      [HttpGet]
        public IActionResult Get()
        {
            return Ok(" Hello from v2");
        }
    }

[Copy paste above code  in editor for better readability/understanding]

Some important point to remember:

1. Make sure that each action method is decorated with proper get/post attribute.
2. Route is specified for each action method.
3. Xml comments are added for each action method.
4. Go to project Properties->build->check-Xml document file. ( if you are using xml comments in swagger)




Resource :
https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md#list-multiple-swagger-documents

Saturday, 15 February 2020

EF Core : Migrations


We have two options to add migrations and update database

1. Using Command line:

  • To add migration "dotnet ef migrations add Initial" where 'Initial' is the name of migration.
  • To Update database " dotnet ef database update" command will update database.

2. Using Package manager console:
  • To add migration " Add-Migration Initial" where Initial is the name of Migration.
  • To Update Database "Update-Databse -migration intial' will update databse.
  • To Revert migration "Update-Database -Migration 0" will revert recently added migration.

Friday, 14 February 2020

How to handle concurrency in EF core (Entity framework core)


Concurrency control in EF Core

e situation when another user has performed an operation that conflicts with the current operation is known as concurrency conflict.
Database providers are responsible for implementing the comparison of concurrency token values.
On relational databases EF Core includes a check for the value of the concurrency token in the WHERE clause of any UPDATE or DELETE statements. After executing the statements, EF Core reads the number of rows that were affected. If no rows are affected, a concurrency conflict is detected, and EF Core throws DbUpdateConcurrencyException.
There are two ways to define concurrency token:
1. by applying [ConcurrencyCheck] attribute like
public class Person { public int PersonId { get; set; } [ConcurrencyCheck] public string LastName { get; set; } public string FirstName { get; set; } }
2. by Adding timestamp property with [TimeStamp] attribute inside entity:
public class Blog { public int BlogId { get; set; } public string Url { get; set; } [Timestamp] public byte[] Timestamp { get; set; } }
In Database query this property will be check like:
UPDATE [Person] SET [FirstName] = @p1 WHERE [PersonId] = @p0 AND [LastName] = @p2; //here LastName property is configure as
//concurrency token.
There are three sets of values available to help resolve a concurrency conflict:
  • Current values are the values that the application was attempting to write to the database.
  • Original values are the values that were originally retrieved from the database, before any edits were made.
  • Database values are the values currently stored in the database.
The general approach to handle a concurrency conflicts is:
  1. Catch DbUpdateConcurrencyException during SaveChanges.
  2. Use DbUpdateConcurrencyException.Entries to prepare a new set of changes for the affected entities.
  3. Refresh the original values of the concurrency token to reflect the current values in the database.
  4. Retry the process until no conflicts occur.
using (var context = new PersonContext()) { // Fetch a person from database and change phone number var person = context.People.Single(p => p.PersonId == 1); person.PhoneNumber = "555-555-5555"; // Change the person's name in the database to simulate a concurrency conflict context.Database.ExecuteSqlRaw( "UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 1"); var saved = false; while (!saved) { try { // Attempt to save changes to the database context.SaveChanges(); saved = true; } catch (DbUpdateConcurrencyException ex) { foreach (var entry in ex.Entries) { if (entry.Entity is Person) { var proposedValues = entry.CurrentValues; var databaseValues = entry.GetDatabaseValues(); foreach (var property in proposedValues.Properties) { var proposedValue = proposedValues[property]; var databaseValue = databaseValues[property]; // TODO: decide which value should be written to database // proposedValues[property] = <value to be saved>; } // Refresh original values to bypass next concurrency check entry.OriginalValues.SetValues(databaseValues); } else { throw new NotSupportedException( "Don't know how to handle concurrency conflicts for " + entry.Metadata.Name); } } } } }

EF core basics


EF Core some common useful operations

Making Relations between entities:

Types of Entities in EF Core:
  • Dependent entity: This is the entity that contains the foreign key properties. Sometimes referred to as the 'child' of the relationship.
  • Principal entity: This is the entity that contains the primary/alternate key properties. Sometimes referred to as the 'parent' of the relationship.
  • Principal key: The properties that uniquely identify the principal entity. This may be the primary key or an alternate key.
  • Foreign key: The properties in the dependent entity that are used to store the principal key values for the related entity.
  • Navigation property: A property defined on the principal and/or dependent entity that references the related entity.
    • Collection navigation property: A navigation property that contains references to many related entities.
    • Reference navigation property: A navigation property that holds a reference to a single related entity.
    • Inverse navigation property: When discussing a particular navigation property, this term refers to the navigation property on the other end of the relationship.
public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } }
  • Post is the dependent entity
  • Blog is the principal entity
  • Blog.BlogId is the principal key (in this case it is a primary key rather than an alternate key)
  • Post.BlogId is the foreign key
  • Post.Blog is a reference navigation property
  • Blog.Posts is a collection navigation property
  • Post.Blog is the inverse navigation property of Blog.Posts (and vice versa)
Relationship between entities

One-to-Many

public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } }


One-to-one

public class Blog { public int BlogId { get; set; } public string Url { get; set; } public BlogImage BlogImage { get; set; } } public class BlogImage { public int BlogImageId { get; set; } public byte[] Image { get; set; } public string Caption { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } }

Many to Many:

public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public List<PostTag> PostTags { get; set; } } public class Tag { public string TagId { get; set; } public List<PostTag> PostTags { get; set; } } public class PostTag { public int PostId { get; set; } public Post Post { get; set; } public string TagId { get; set; } public Tag Tag { get; set; } }

Operations on Entities:

Saving Data


Each context instance has a ChangeTracker that is responsible for keeping track of changes that need to be written to the database. As you make changes to instances of your entity classes, these changes are recorded in the ChangeTracker and then written to the database when you call SaveChanges. The database provider is responsible for translating the changes into database-specific operation.

Adding Data

DBSet.Add method is used to add data, after adding data we need to call SaveChanges() method.

for example, we have a entity called Employee, to add employee object to database we need to write following code:

context.Employees.Add(objEmployee);
context.SaveChanges();

Updating Data

To Update data, we firstly need to search required entity which we want to update and then need to change it's properties and then need to save it.

var emp = context.Employees.First(); emp.FirstName= "New Name"; context.SaveChanges();

Deleting Data

var emp = context.Employees.First();
context.Employees.Remove(emp); context.SaveChanges();

Adding a new entities hierarchically


using (var context = new BloggingContext()) { var blog = new Blog { Url = "http://blogs.msdn.com/dotnet", Posts = new List<Post> { new Post { Title = "Intro to C#" }, new Post { Title = "Intro to VB.NET" }, new Post { Title = "Intro to F#" } } }; context.Blogs.Add(blog); context.SaveChanges(); }

Use the EntityEntry.State property to set the state of just a single entity. For example, context.Entry(blog).State = EntityState.Modified.

Adding a related entity

adding a new post to the post collection of a blog

using (var context = new BloggingContext()) { var blog = context.Blogs.Include(b => b.Posts).First(); var post = new Post { Title = "Intro to EF Core" }; blog.Posts.Add(post); context.SaveChanges(); }

Changing relationships

In the following example, the post entity is updated to belong to the new blog entity because its Blog navigation property is set to point to blog. Note that blog will also be inserted into the database because it is a new entity that is referenced by the navigation property of an entity that is already tracked by the context (post).

using (var context = new BloggingContext()) { var blog = new Blog { Url = "http://blogs.msdn.com/visualstudio" }; var post = context.Posts.First(); post.Blog = blog; context.SaveChanges(); }

Removing relationships

In the following example, a cascade delete is configured on the relationship between Blog and Post, so the post entity is deleted from the database.

using (var context = new BloggingContext()) { var blog = context.Blogs.Include(b => b.Posts).First(); var post = blog.Posts.First(); blog.Posts.Remove(post); context.SaveChanges(); }


How to create and use middleware in asp.net core

Middleware is piece of code that's assembled into an app pipeline to handle requests and responses.  Each middleware component in the re...