Tech Point Fundamentals

Sunday, December 25, 2022

.Net Core Interview Questions and Answers - Part 17

ASP.Net Core Interview Questions and Answers - Part 17

AspDotNetCoreInterviewQuestionsAndAnswers

Are you preparing for the .Net Core Interview? If yes, then you are at the right place. This is the ASP.Net Core Interview Questions and Answers article series. Here we will see the Top 150+ .Net Core Interview Questions with Answers. 

Please visit our YouTube Channel for Interviews and other videos by below link:




Please read the complete Design Pattern, C#, MVC, WebAPI, and .Net Framework Interview Questions and Answers article series here.




Introduction


This is the 17th part of the .Net Core Interview Questions and Answers article series. Each part contains ten .Net Core Interview Questions. Please read all the .Net Interview Questions list here.

I will highly recommend to please read the previous parts over here before continuing the current part:







ASP.Net Core Interview Questions and Answers - Part 17


Q166. What is Entity Framework Core? How can you use Entity Framework Core in ASP.Net Core?

Entity Framework Core is an ORM (Object-Relational Mapper). It's a complete rewrite from the ground up for the core. EF core is lightweight, extensible, and open-source software. Like .NET Core, EF Core is also cross-platform. It works on Windows, Mac OS, and Linux. EF Core is Microsoft’s official data access platform.

Required NuGet Packages:

You need to install the following NuGet packages in order to use EF Core:

Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

Following are the key components and steps to use the EF Core in ASP.Net core applications:



EF Core DbContext class:

One of the very important classes in Entity Framework Core is the DbContext class. This is the class that we use in our application code to interact with the underlying database.

This class manages the database connection and is used to retrieve and save data in the database. The DbContext class is available in Microsoft.EntityFrameworkCore namespace.

EF Core DbContextOptions:

For the DbContext class to be able to do any useful work, it needs an instance of the DbContextOptions class. The DbContextOptions instance carries configuration information such as the connection string, database provider to use, etc. We pass the DbContextOptions to the base DbContext class constructor using the base keyword.



EF Core DbSet:

The DbContext class includes a DbSet<TEntity> property for each entity in the model. EF Core looks for all the public DbSet properties, inside the application’s context class, and then maps their names to the names of the tables in the database. 

Then it goes inside a class that is provided in the DbSet<T> property and maps all the public properties to the table columns in the table with the same names and types.

We use these DbSet properties to query and save instances of the entity (Employee and Department) classes. The LINQ queries against the DbSet properties will be translated into queries against the underlying database.

If our entity class has any references toward other entity classes EF Core would use those reference properties and create relationships in the database.



EF Core OnModelCreating() Method:

You can override the OnModelCreating() method to seed the entity date (Employee and Department) if any.

public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}

public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Employees { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
base.OnModelCreating(modelBuilder);    
    }
}


Defining Database Connection String:

You need to define the database connection string in the appsettings.json file:

"ConnectionStrings": {
  "DBConnection": "server=(localdb)\\MSSQLLocalDB;database=EmployeeDB;Trusted_Connection=true"
}



Registering the DbContext Class in the ASP.NET Core’s IoC:

After we have finished creating the AppDbContext class, we can proceed toward its registration. Register the DbContext service in ConfigureServices of the Startup class:

public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DBConnection")));

services.AddControllers();
}

We are using the AddDbContext extension method to register our AppDbContext class into the IOC container. Inside the UseSqlSrver method, we are providing the connection string to our context class and we can provide additional options as well.

Instead of the AddDbContext method, we can use the AddDbContextPool method. We can use either the first or the second method, but with the second method, we enable DbContext pooling. This will not create a new instance every time but will check first if there are available instances in the pool and if there are, it will use one of those.



DB Migration:

After that, you can execute the database migration commands to create and execute the initial database migration:

Add-Migration InitialCreate
Update-Database

Using EF Context in the Controller:

Now our context class is ready to be used with the Dependency Injection inside our application.

public class ValuesController : ControllerBase
{
private readonly AppDbContext _context;
public ValuesController(AppDbContext context)
{
_context = context;
}
}




Q167. What is Database or EF Core Migration in ASP.Net Core? Why do we need the DB Migration? 

When you develop a new application, your data model changes frequently as new features get implemented, and each time the model changes, it gets out of sync with the database.

If you configure the Entity Framework to create the database if it doesn't exist. Then each time you change the data model (add, remove, or change entity classes or change your DbContext class), you can delete the database and EF creates a new one that matches the model, and seeds it with test data.

This method of keeping the database in sync with the data model works well until you deploy the application to production. 

When the application is running in production it's usually storing data that you want to keep, and you don't want to lose everything each time you make a change such as adding a new column. The EF Core Migrations feature solves this problem by enabling EF to update the database schema instead of creating a new database.



Migrations:

The migrations feature in EF Core provides a way to incrementally update the database schema to keep it in sync with the application's data model while preserving existing data in the database. Migration is a way to keep the database schema in sync with the EF Core model by preserving data.

EF Core API builds the EF Core model from the domain (entity) classes and EF Core migrations will create or update the database schema based on the EF Core model. Whenever you change the domain classes, you need to run the migration to keep the database schema up to date.

When a data model change is introduced, the developer uses EF Core tools to add a corresponding migration describing the updates necessary to keep the database schema in sync. EF Core compares the current model against a snapshot of the old model to determine the differences, and generates migration source files; the files can be tracked in your project's source control like any other source file.

Once a new migration has been generated, it can be applied to a database in various ways. EF Core records all applied migrations in a special history table, allowing it to know which migrations have been applied and which haven't.



Required Tools:

The EF tooling for managing migrations is available from .NET Core CLI commands or from PowerShell cmdlets in the Visual Studio Package Manager Console (PMC) window.

The EF commands for the PMC commands are available in Microsoft.EntityFrameworkCore.Tools package. This package is included in Microsoft.AspNetCore.App metapackage, so you don't need to add a package reference if your app has a package reference for Microsoft.AspNetCore.App.


Migration Commands:

To work with migrations, you can use the Package Manager Console (PMC) or the  .NET Core CLI tools. The  .NET Core CLI tools work on all platforms while PMC works inside the Visual Studio.

EF Core migrations are a set of commands which you can execute in NuGet Package Manager Console or in dotnet Command Line Interface (CLI).

EFMigrationCommands




Add First Migration:

At the very first time, when you defined the initial domain classes, there is no database for your application that can store the data from your domain classes. So, firstly, you need to create a migration.

If you want to delete the existing database if any you can use any of the following commands:

PM> Drop-Database
dotnet ef database drop

Open the Package Manager Console from the menu Tools -> NuGet Package Manager -> Package Manager Console in Visual Studio and execute the following command to add a migration.

PM> add-migration InitialCreate 

If you are using dotnet CLI  execute the following command:

dotnet ef migrations add InitialCreate

When you executed the migrations add command, EF generated the code that will create the database from scratch. EF Core will create a directory called Migrations in your project, and generate some files as well:



1. <timestamp>_<Migration Name>.cs: 

This is the main migration file which includes migration operations in the Up() and Down() methods. The Up() method includes the code for creating DB objects and Down() method includes code for removing DB objects. 

The Up method of the InitialCreate class creates the database tables that correspond to the data model entity sets, and the Down method deletes them. Migrations calls the Up method to implement the data model changes for a migration. When you enter a command to roll back the update, Migrations calls the Down method.

2. <timestamp>_<Migration Name>.Designer.cs:  This is the migrations metadata file which contains information used by EF Core.

3. <contextclassname>ModelSnapshot.cs: This is a snapshot of your current model. This is used to determine what changed when creating the next migration.


If you created the initial migration when the database already exists, the database creation code is generated but it doesn't have to run because the database already matches the data model. 




Creating or Updating the Database:

Now, after creating a migration snapshot, it's time to create the database. At this point, you can have EF create your database and create your schema from the migration. Use any of the following commands to create or update the database schema.

PM> Update-Database 
dotnet ef database update

The Update command will create the database based on the context and domain classes and the migration snapshot, which is created using the add-migration or add command.

If this is the first migration, then it will also create a table called __EFMigrationsHistory, which will store the name of all migrations,  as and when they will be applied to the database.



Removing a Migration:

You can remove the last migration if it is not applied to the database. Use any of the following commands to remove the last created migration files and revert the model snapshot:

PM> remove-migration
dotnet ef migrations remove

The above commands will remove the last migration and revert the model snapshot to the previous migration. But if a migration is already applied to the database, then it will throw the exception.

The migration <migration name> has already been applied to the database. Revert it and try again. If the migration has been applied to other databases, consider reverting its changes using a new migration.



Reverting a Migration:

You can also revert the complete migration if not required at all.  Suppose you changed your domain class and created the second migration named SecondMigration using the add-migration command and applied this migration to the database using the Update command. But, for some reason, you want to revert the database to the previous state.

Here use the update-database <migration name> command to revert the database to the specified previous migration snapshot:

Update-database FirstMigration
dotnet ef database update FirstMigration

The above command will revert the database based on a migration named FirstMigration and remove all the changes applied for the second migration named SecondMigration. 

This will also remove the SecondMigration entry from the __EFMigrationsHistory table in the database. But it will not remove the migration files related to SecondMigration. You need to use the remove commands to remove them from the project.



Generating a SQL Script:

You can use any of the following commands to generate a SQL script for the database.

PM> script-migration
dotnet ef migrations script

The above script command will include a script for all the migrations by default. You can specify a range of migrations by using the -to and -from options.

Excluding Model from Migration:

This feature was introduced in EF Core 5.0. Sometimes you may want to reference types from another DbContext. This can lead to migration conflicts. To prevent this, exclude the type from the migrations of one of the DbContexts.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IdentityUser>()
.ToTable("AspNetUsers", t => t.ExcludeFromMigrations());
}



Q168. What is CORS? How to enable CORS in ASP.NET Core?

Same Origin Policy:

Two URLs are considered to have the same origin if they have:

  1. The same URL scheme (HTTP or HTTPS), 
  2. Same hostname (domain name), 
  3. And the same port number 

So two URLs have the same origin if they have identical schemes, hosts, and ports. For example https://example.com/foo.html and https://example.com/bar.html.

The Same-Origin Policy states that a Web browser will only allow communication between two URLs if they belong to the same origin. This policy exists to isolate potentially malicious scripts from harming other documents on the web.

For example, the client app https://example.net cannot communicate with the server app https://www.example.com as they belong to a different origin. 

Browser security prevents a web page from making requests to a different domain than the one that served the web page. This restriction is called the same-origin policy. The same-origin policy prevents a malicious site from reading sensitive data from another site.

But there are some cases where Cross-Domain scripting is desired and the idea of the open web makes it compelling.



Cross-Origin Policy:

CORS stands for Cross-Origin Resource Sharing. CORS is a mechanism to bypass the Same-Origin policy of a Web browser. 

All modern browsers set the Origin header automatically, which indicates the domain of the site is making the request. If the server allows Cross-origin requests from the Origin, it sets the Access-Control-Allow-Origin header with its value matching the origin header’s value from the request.

If the server doesn’t include this header, the request fails. The browser will receive the response data, but this data shall not be accessible to the client.



Enabling CORS in ASP.NET Core Middleware:

There are following three ways to enable the CORS in ASP.Net Core apps:

  1. Using Middleware
  2. Using Endpoint Routing
  3. With [EnableCors] Attribute
In all of the above methods using the [EnableCors] attribute with a named policy provides the finest control in limiting endpoints that support CORS.

Please remember that UseCors() must be called in the correct order. For example, UseCors must be called before UseResponseCaching when using UseResponseCaching.



Q169. How can you enable CORS by using middleware in ASP.NET Core? What is the use of UseCors() middleware?

CORS Middleware handles cross-origin requests.  First, we create a private variable to hold the name of our CORS policy. 

Then, in the ConfigureServices method, we call the AddCors() method that adds cross-origin resource sharing services to the service collection. This method accepts an Action delegate as a parameter where we can configure the CORS options. 

public class Startup
{
private readonly string _policyName = "CorsPolicy";
 
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(opt =>
{
opt.AddPolicy(name: _policyName, builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
}
public void Configure(IApplicationBuilder app)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(_policyName);
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}



For the CORS options, we call the AddPolicy method, which adds a new policy to the configuration and also accepts an Action delegate as a parameter where we can set up the methods to build our policy. 

With this policy, we enable access from any origin AllowAnyOrigin, allow any header in a request AllowAnyHeader, and allow any method AllowAnyMethod. Also in the Configure method, we call the UseCors method and pass the policy name to add the CORS middleware to the application’s pipeline. 

CORS Rule:

  1. It is very important to note that the UseCors() method must be called after the UseRouting method and before the UseAuthorization method. 
  2. When using Response Caching Middleware, call UseCors before UseResponseCaching.
  3. Typically, UseStaticFiles is called before UseCors. Apps that use JavaScript to retrieve static files cross-site must call UseCors before UseStaticFiles.
  4. With endpoint routing, the CORS middleware must be configured to execute between the calls to UseRouting and UseEndpoints.
  5. If you are using the Url in the WithOrigins option then the specified URL must not contain a trailing slash (/). If the URL terminates with /, the comparison returns false and no header is returned.



options.AddPolicy(MyAllowSpecificOrigins,
  policy =>
  {
  policy.WithOrigins("http://example.com",
  "http://www.contoso.com")
  .AllowAnyHeader()
  .AllowAnyMethod();
  });

If we don’t want to use multiple named policies but a single default policy, we can replace the AddPolicy method with the AddDefaultPolicy method:

services.AddCors(opt =>
{
opt.AddDefaultPolicy(builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});

In this case, we don’t have to provide the policy name in the UseCors method as well:

app.UseRouting();
app.UseCors();
app.UseAuthorization();

This policy is not the strict one, but it is a basic setup that will remove the CORS issue for our client application.



Q170. How can you enable CORS by Endpoint Routing in ASP.NET Core

Enabling CORS on a per-endpoint basis using RequireCors does not support automatic preflight requests. With endpoint routing, CORS can be enabled on a per-endpoint basis using the RequireCors set of extension methods:

private readonly string _policyName = "CorsPolicy";
 
public void ConfigureServices(IServiceCollection services)
{  
builder.Services.AddCors(options =>
{
options.AddPolicy(name: _policyName,
  policy =>
  {
  policy.WithOrigins("http://example.com",
         "http://www.contoso.com");
  });
});
}

public void Configure(IApplicationBuilder app)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/echo",
context => context.Response.WriteAsync("echo"))
.RequireCors(_policyName);

endpoints.MapControllers()
.RequireCors(_policyName);

endpoints.MapGet("/echo2",
context => context.Response.WriteAsync("echo2"));

endpoints.MapRazorPages();
});
}



Here:

  1. The app.UseCors enables the CORS middleware because a default policy has not been configured, app.UseCors() alone doesn't enable CORS.
  2. The /echo and controller endpoints allow cross-origin requests using the specified policy.
  3. The /echo2 and Razor Pages endpoints do not allow cross-origin requests because no default policy was specified.

But remember the [DisableCors] attribute does not disable CORS that has been enabled by endpoint routing with RequireCors.



Q171. How can you enable CORS by Attributes in ASP.NET Core

Sometimes we only want to allow CORS requests to a selected few methods, instead of enabling CORS at the entire application level, we can also enable CORS at the controller level or at the action level. 

For that, we have to use the [EnableCors] attribute. We can use just the [EnableCors] attribute on top of the controller or the action, and it will implement a default CORS policy. Or we can use the [EnableCors("Policy name")] attribute, to apply a named CORS policy.

By using the named policy with the [EnableCors] attribute, we can apply different policies to different controllers or actions. So Enabling CORS with the [EnableCors] attribute and applying a named policy to only those endpoints that require CORS provides the finest control.

[EnableCors] specifies the default policy.
[EnableCors("{Policy String}")] specifies a named policy.



The [EnableCors] attribute can be applied to Razor Page PageModel, Controller, or Controller action method. Different policies can be applied to controllers, page models, or action methods with the [EnableCors] attribute. 

When the [EnableCors] attribute is applied to a controller, page model, or action method, and CORS is enabled in middleware, both policies are applied.

private readonly string _policyName = "CorsPolicyOne";
private readonly string _secondPolicy = "CorsPolicyTwo";

public void ConfigureServices(IServiceCollection services)
{
services.AddCors(opt =>
{
opt.AddPolicy(name: _policyName, builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
opt.AddPolicy(name: _secondPolicy, builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
}



Also, we have to modify the Configure method as well:

 public void Configure(IApplicationBuilder app)
 {
app.UseRouting();
app.UseCors();
 }

Please note that here we are not specifying the policy name since we are using more than one policy in our application. Also, we are not using endpoint routing.

Now you can use the [EnableCors] attributes on the controller or action where required:

[EnableCors("CorsPolicyOne")]
public IActionResult Foo()
{
return Ok("This action is protected with CorsPolicyOne CORS policy");
}

In the previous CORS setting, for both policies, we are allowing any origin, any header, and any method. 



But we can use different options while adding policies to the CORS configuration.  You can define different origins as well for different policies:

opt.AddPolicy(name: _policyName, builder =>
{
builder.WithOrigins("https://localhost:5011")
.AllowAnyHeader()
.AllowAnyMethod();
});
opt.AddPolicy(name: _anotherPolicy, builder =>
{
builder.WithOrigins("https://localhost:5021")
.AllowAnyHeader()
.AllowAnyMethod();
});

Here we are using the WithOrigins method, which accepts a params string[] origins as a parameter.

If we want to allow access to multiple origins for a single policy, we can just add multiple comma-separated URIs as an argument: WithOrigins("First URI", "Second URI"). 




Q172. How can you specify the CORS for multiple subdomains in the ASP .Net Core app? - OR -
What is SetIsOriginAllowedToAllowWildcardSubdomains method?

When we want to allow access for a client that has a main domain and multiple subdomains, we don’t have to add all the URIs with subdomains as arguments.

What we can do is use the wildcard in the WithOrigins method followed by the SetIsOriginAllowedToAllowWildcardSubdomains method: 

opt.AddPolicy(name: _policyName, builder =>
{
builder.WithOrigins("https://*.techpointfunda.com")
.SetIsOriginAllowedToAllowWildcardSubdomains();
});

Here, by using the SetIsOriginAllowedToAllowWildcardSubdomains method, we allow origins to match a configured wildcard domain when evaluating if the origin is allowed.



Q173. How can you specify the CORS only for the GET type method in the ASP .Net core?

You can also enable the CORS for Specific Method Type as well:

opt.AddPolicy(name: _policyName, builder =>
{
builder.WithOrigins("https://localhost:5011")
.AllowAnyHeader()
.WithMethods("GET");
});

Now, instead of AllowAnyMethod, we are using WithMethods, which accepts params string[] methods as a parameter. 

So if we want to allow access to multiple methods, we need to add them as multiple comma-separated strings: WithMethods("PUT", "DELETE", "GET").



Enabling CORS for Specific Headers:

Similarly, we can also enable CORS for specific Headers by using the WithHeaders option as well. We can use the WithHeaders method to allow specific headers to be sent in a CORS request.

opt.AddPolicy(name: _anotherPolicy, builder =>
{
builder.WithOrigins("https://localhost:5021")
.WithHeaders(HeaderNames.ContentType, HeaderNames.Accept)
.WithMethods("GET");
});



Exposing Headers in CORS:

 If your API is exposing any header for example "X-Pagination" :

[HttpGet]
public async Task<IActionResult> Get([FromQuery] search)
{
var products = await _repo.GetRecords(search);
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(products.MetaData));
return Ok(products);
}

In this case, for the client application to be able to access that information inside the header, we have to expose it in the CORS configuration:

opt.AddPolicy(name: _anotherPolicy, builder =>
{
builder.WithOrigins("https://localhost:5021")
.WithHeaders(HeaderNames.ContentType, HeaderNames.Accept)
.WithMethods("GET")
.WithExposedHeaders("X-Pagination");
});




Q174. How can you disable the CORS in ASP.Net Core app?

Sometimes we need to disable CORS on the action or the controller level.  To do that, we can use the [DisableCors] attribute:

[DisableCors]
[HttpGet]
public async Task<IActionResult> Post(UserModel model)
{
return Ok(products);
}

But please note that the [DisableCors] attribute does not disable CORS that have been enabled by endpoint routing.



To Be Continued Part-18...


Recommended Articles






Thanks for visiting this page. Please follow and join us on LinkedInFacebookTelegramQuoraYouTubeTwitterPinterestTumbler, and VK for regular updates.

    

No comments:

Post a Comment

Please do not enter any HTML. JavaScript or spam link in the comment box.