Tech Point Fundamentals

Sunday, November 20, 2022

.Net Core Interview Questions and Answers - Part 12

ASP.Net Core Interview Questions and Answers - Part 12

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 12th 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 12


Q114. How does the next parameter of the delegate know how to call the next piece of middleware in the HTTP processing pipeline?  What is the Request Delegate in .Net Core?

Each middleware component has an Invoke method with an HttpContext argument. You can use this argument to handle the request and generate a response if applicable.

The topmost piece of middleware in the application will always get called for each request. This is done automatically by the framework. This middleware may send a response to the client, or it may call the next piece of middleware. This is why most middleware components are defined with a constructor that takes a RequestDelegate argument.

The RequestDelegate is populated automatically and gives you a reference to the next piece of middleware in the pipeline. We typically store the RequestDelegate so we can call it from the Invoke method which is where the middleware does its work.

public class MyMiddleware
{
private readonly RequestDelegate _next;

  public MyMiddleware(RequestDelegate next, OtherDependencies...)
  {
_next = next;
  }
}



Request delegates handle each HTTP request and are used to build a request pipeline. It can be configured using Run, Map, and Use extension methods.

A request delegate can be an in-line as an anonymous method (called in-line middleware) or a reusable class. These classes or in-line methods are called middleware components.

Each piece of middleware has two chances to do some work - once before the next middleware is called (in-phase) and once after (out-phase). The typical structure of a middleware's Invoke method:

public async Task Invoke(HttpContext context)
{
// IN Phase => code executed before the next middleware
await _next.Invoke(context); // call next middleware

// OUT Phase => code executed after the next middleware
}






Q115. How can you register a middleware in the .Net Core application?

Middleware is registered in the Configure method of Startup.cs. The Configure method has an IApplicationBuilder argument that provides the methods necessary for all types of middleware registration.

The standard way to register middleware that applies to all requests is with UseMiddleware:

public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<MyCustomMiddleware>();
}

But in reality, we rarely need to call UseMiddleware directly because the standard approach for middleware creators is to write extension methods specific to the middleware being registered as we have done in the previous Q107 and Q108:

public void Configure(IApplicationBuilder app)
{
app.UseMyCustomMiddleware();
}



Behind the scenes, the extension method normally just registers the middleware with UseMiddleware:

public static class MyCustomMiddlewareExtensions
{
public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<MyCustomMiddleware>();

return app;
}
}

The only reason for using the custom extension method is only slightly more readable and easier to use than the original UseMiddleware approach. Use* extensions methods are the standard way to register middleware applicable to all requests. 




Q116. What is Conditional middleware? How can you add conditional middleware in .Net Core?

Sometimes we want most of the middleware to run for all requests but we have some conditional or specific middleware that should only run for certain requests. This is easily achieved with UseWhen which also uses a predicate to determine if the middleware should run. 

Map series extension methods, such as UseWhen and MapWhen, are often used to shunt pipeline operations. The map is based on the Request path and the MapWhen is based on the assignment-predicated verb. The MapWhen method takes two parameters: Func<HttpContext, bool> predicate, and delegate action.

The UseWhen method can be used for conditional execution middleware.  unlike MapWhen, UseWhen will continue to execute the following next middleware logic, regardless of whether the current delegate function of UseWhen returns true or false. 



On the other hand, MapWhen allows you to split the middleware pipeline into two completely separate branches by specifying a predicate.

app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
{
appBuilder.UseStatusCodePagesWithReExecute("/apierror/{0}");

appBuilder.UseExceptionHandler("/apierror/500");
});

The predicate approach provides a lot of flexibility and you can conditionally apply middleware based on cookies, headers, current users and much more. Here the above code uses different error-handling middleware when the request is for the API.



As with MapWhen, all middleware registered before the UseWhen call will apply to all requests. The primary difference between UseWhen and MapWhen is how later (registered below) middleware is executed. Unlike MapWhen, UseWhen continues to execute later middleware regardless of whether the UseWhen predicate was true or false.

app.UseMiddlewareOne();
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
{
appBuilder.UseMiddlewareTwo();
});
app.UseMiddlewareThree();

Here this time, assuming there is no short-circuiting, middleware One and Three will be executed in all cases. Middleware Two will only be executed if the request path starts with '/api'.

UseWhen() is very powerful and incredibly useful. Rather than the middleware itself deciding on if it should execute (perhaps via configuration), we can control the middleware ourselves by choosing how we register it.



Q117. What are Request Feature Interfaces and Feature Collections? What are the different feature properties of HttpContext? 

In ASP.NET Core, a request feature is an entity created during a user’s HTTP request. The entity is generally created within middleware for the purpose of allowing developers to enhance or modify the current application’s hosting pipeline. These features are accessible via the HttpContext of an incoming request.

The Features property of HttpContext provides an interface for getting and setting the available HTTP features for the current request. Since the feature collection is mutable even within the context of a request, middleware can be used to modify the collection and add support for additional features.

HttpContext.Features.Get<MyAwesomeFeature>();

The Features property of HttpContext provides access to the collection of feature interfaces for the current request. Since the feature collection is mutable even within the context of a request, middleware can be used to modify the collection and add support for additional features. 



Individual web server features related to how HTTP requests and responses are handled have been factored into separate interfaces. These abstractions are used by individual server implementations and middleware to create and modify the application’s hosting pipeline.

The HttpContext API that applications and middleware use to process requests has an abstraction layer underneath it called feature interfaces. Each feature interface provides a granular subset of the functionality exposed by HttpContext. 

These interfaces can be added, modified, wrapped, replaced, or even removed by the server or middleware as the request is processed without having to re-implement the entire HttpContext. They can also be used to mock functionality when testing.



ASP.Net Core Features:

ASP.NET Core defines a number of HTTP feature interfaces in Microsoft.AspNetCore.Http.Features that are used by servers to identify the features they support. The following feature interfaces handle requests and return responses. 

For example: IHttpRequestFeature, IHttpResponseFeature, IHttpResponseBodyFeature, IHttpAuthenticationFeature, IHttpRequestLifetimeFeature etc.



Middleware vs Request Features:

While servers are responsible for creating the feature collection, middleware can both add to this collection and consume features from the collection.

Additionally, middleware can add to the feature collection established by the server. Existing features can even be replaced by middleware, allowing the middleware to augment the functionality of the server. Features added to the collection are available immediately to other middleware or the underlying application itself later in the request pipeline.

By combining custom server implementations and specific middleware enhancements, the precise set of features an application requires can be constructed. This allows missing features to be added without requiring a change in the server and ensures only a minimal amount of features are exposed, thus limiting attack surface area and improving performance.



Q118. What is URL Rewriting? What is the difference between URL Redirect vs URL Rewrite?  

URL rewriting is the act of modifying request URLs based on one or more predefined rules. URL rewriting creates an abstraction between resource locations and their addresses so that the locations and addresses aren't tightly linked.

When to use URL Rewriting:

  1. Move or replace server resources temporarily or permanently and maintain stable locators for those resources.
  2. Split request processing across different apps or across areas of one app.
  3. Remove, add, or reorganize URL segments on incoming requests.
  4. Optimize public URLs for Search Engine Optimization (SEO).
  5. Permit the use of friendly public URLs to help visitors predict the content returned by requesting a resource.
  6. Redirect insecure requests to secure endpoints.
  7. Prevent hotlinking, where an external site uses a hosted static asset on another site by linking the asset into its own content.

Since URL rewriting can reduce the performance of an app, and limit the number and complexity of rules.






URL Redirect vs URL Rewrite:

There is a subtle difference between URL redirect and URL rewrite. ASP.NET Core's URL Rewriting Middleware is capable of doing both. Both URL redirection and the rewriting tasks can be done in Configure() method of the startup.cs file in ASP.Net Core. 

Actually, there are two different ways to change the current request's endpoint: Rewrite the current URL and Redirect to an external URL. The two tasks are similar yet different in their execution:

Rewriting actually changes the current request's path internally and continues processing the current request with all of it's existing state through the middleware pipeline. 

Any middleware registered after the rewrite sees the new URL and processes the remainder of the request with the new path. All of this happens as a part single server request.

But the URL of the request displayed in the address bar stays the same - the browser location doesn't change to the rewritten URL (context.Request.Path).



On the other hand, Redirecting actually fires a new request on the server by triggering a new HTTP request in the browser via a 302 Moved or 301 Moved Permanently HTTP Response header that contains the redirection URL.

A URL Redirect involves a client-side operation, where the client is instructed to access a resource at a different address than the client originally requested. This requires a round trip to the server. The redirect URL returned to the client appears in the browser's address bar when the client makes a new request for the resource.

If /resource is redirected to /different-resource, the server responds that the client should obtain the resource at /different-resource with a status code indicating that the redirect is either temporary or permanent.

UrlRedirect
Source: Microsoft Docs

The 301 - Moved Permanently status code is used where the resource has a new, permanent URL and that all future requests for the resource should use the new URL. The client may cache and reuse the response when a 301 status code is received.



Redirects can use 301 Moved Permanently to let search engines know that the old URL is deprecated and the new URL should be used instead. It use context.Response.Redirect().

The 302 - Found status code is used where the redirection is temporary or generally subject to change. The 302 status code indicates to the client not to store the URL and use it in the future.

A redirect is an HTTP header response to the client that instructs the client to: Go to the URL specified in this response header.

HTTP/1.1 302 Moved
Location: https://west-wind.com/wwwhelp

On the other hand, a URL Rewrite is a server-side operation that provides a resource from a different resource address than the client requested. Rewriting a URL doesn't require a round trip to the server. The rewritten URL isn't returned to the client and doesn't appear in the browser's address bar.



If /resource is rewritten to /different-resource, the server internally fetches and returns the resource at /different-resource. 

UrlReWrite
Source: Microsoft Docs

Although the client might be able to retrieve the resource at the rewritten URL, the client isn't informed that the resource exists at the rewritten URL when it makes its request and receives the response.

If you have a choice between re-writing and a redirect, the rewrite tends to be more efficient as it avoids a server round trip by simply re-writing the URL as part of the current request. The caveat is that the browser's location/address bar does not reflect the new rewritten URL - if that's important (and often it is) then a redirect is required.

A rewrite can also keep request information, so if you have POST or PUT operation that has data associated with it, that data stays intact. A Redirect() on the other hand is always reissued as an HTTP GET operation by the browser so you can't redirect from input.






Q119. How can you add URL Rewriting Middleware in .Net Core? How it is different from traditional ASP.Net Core Rewriting?

URL rewriting is the concept of changing the currently executing URL and pointing it at some other URL to continue processing the current request or redirecting to an external URL.

In classic ASP.NET you could use HttpContext.RewritePath() but that doesn't exist in .NET Core. So if you plan to intercept requests and rewrite them, the most likely place you'd want to do this is in ASP.NET Core Middleware.

You should use URL Rewriting Middleware when it is not satisfactory to do it from the web server like IIS, Apache, Nginx, etc.  Use the URL rewriting middleware when the app is hosted on HTTP.sys server. The main reasons to use the server-based URL rewriting technologies in IIS, Apache, and Nginx are:

  • The middleware doesn't support the full features of these modules. Some of the features of the server modules don't work with ASP.NET Core projects, like IsFile and IsDirectory.
  • The performance of the middleware probably doesn't match that of the modules.



The Rewrite middleware components tend to look at incoming request paths or headers and determine whether they need to re-write the URL to something else. The easiest way to do this is to use app.Use() inline middleware which you can add to your Startup.Configure() method.

Both URL redirection and the rewriting tasks can be done in Configure() method of the startup.cs file in ASP.Net Core. 

app.Use(async (context,next) =>
{
var url = context.Request.Path.Value;
if (url.Contains("/home/privacy"))
{
context.Request.Path = "/home/index";
}
await next();
});

All subsequent middleware components now see the updated path.

You can use a similar approach for Redirecting as well, but the logic is slightly different because a Redirect is a new request and you'll want to terminate the middleware pipeline.



It is a good idea to short-circuit the Response when redirecting, rather than continuing through the rest of the middleware pipeline. Please note that Response.Redirect() in ASP.NET Core doesn't do automatic path fixups as classic ASP.NET did. You can use Response.Redirect("~/docs/MarkdownDoc.md") but you have to specify the whole path.

app.Use(async (context,next) =>
{
var url = context.Request.Path.Value;
if (url.Contains("/home/"))
{
context.Response.Redirect("https://techpointfunda.com", true)
return;   // short circuit
}
await next();
});

In context.Response.Redirect, if you passed the second parameter as true then your redirect will work as a permanent redirect with 301 as HTTP status, which helps you in Search Engine Optimization (SEO).

Redirects are more commonly used when you need to redirect as part of your application/controller logic, where you can't use a rewrite operation because the path has already been routed to your application endpoint/controller method.

Unless your target URL includes application external URLs,  there's no good reason to use a Redirect in middleware. It only makes sense for external, non-application URLs in that scenario.



Q120. How can you get parameters from the Requested URL in ASP.Net Core? 

URLs are made up of several parts, like protocol, hostname, path, and so on. The query string is the part of the URL that comes after a question mark character. Everything after the ? character is considered the query string. 

https://www.google.com/search?q=test&oq=techpoint

Access to the query string in ASP.NET MVC is very simple - just use the HttpContext class. 
The information about the query string is located using one of the following properties: HttpContext.Request.QueryString and HttpContext.Request.Query. The difference is that the QueryString is basically the raw text string, while the Query property allows you to easily access keys and their values.

You can also use static ParseQueryString() method of System.Web.HttpUtility class that returns NameValueCollection. ParseQueryString() method parses a query string into a NameValueCollection using UTF8 encoding.

string param = System.Web.HttpUtility.ParseQueryString(Uri.Query).Get("param");







Q121. What is Model Binding in ASP.Net Core Application? 

Controllers and Razor pages work with data that comes from HTTP requests via different modes like URI, Headers, Cookies, Body, etc. Writing code to retrieve each of these values and convert them from strings to .NET types would be tedious and error-prone. Model binding automates this process. 

The model binding system:

  1. Retrieves data from various sources such as route data, form fields, and query strings.
  2. Provides the data to controllers and Razor pages in method parameters and public properties.
  3. Converts string data to .NET types.
  4. Updates properties of complex types.

After each property is successfully bound, model validation occurs for that property. The record of what data is bound to the model, and any binding or validation errors, is stored in ControllerBase.ModelState or PageModel.ModelState. To find out if this process was successful, the app checks the ModelState.IsValid flag.






By default, model binding gets data in the form of key-value pairs from the following sources in an HTTP request:

  1. Form fields
  2. The request body (in the case of API)
  3. Route data
  4. Query string parameters
  5. Uploaded files

For each target parameter or property, the sources are scanned in the order indicated in the above list, But:

  1. Route data and query string values are used only for simple types.
  2. Uploaded files are bound only to target types that implement IFormFile or IEnumerable<IFormFile>.

So if the default source is not correct, use one of the following attributes to specify the source:

  1. [FromQuery]: Gets values from the query string.
  2. [FromRoute]: Gets values from route data.
  3. [FromForm]: Gets values from posted form fields.
  4. [FromBody]: Gets values from the request body.
  5. [FromHeader]: Gets values from HTTP headers.



Q122. What is the use of the [BindRequired] attribute in ASP.Net Core?

By default, a model state error isn't created if no value is found for a model property.  The property is set to null or a default value:

  1. Nullable simple types are set to null.
  2. Non-nullable value types are set to default(T). For example, a parameter int id is set to 0.
  3. For complex Types, model binding creates an instance by using the default constructor, without setting properties.
  4. Arrays are set to Array.Empty<T>(), except that byte[] arrays are set to null.

So if the model state should be invalidated when nothing is found in form fields for a model property, we use the [BindRequired] attribute.

Note that this [BindRequired] behavior applies to model binding from posted form data, not to JSON or XML data in a request body. Request body data is handled by input formatters.






Q123. What is the [BindProperty] attribute in ASP.Net Core Application?

Actually, the default Model binding tries to find values for the following kinds of targets:

  1. Parameters of the controller action method that a request is routed to.
  2. Parameters of the Razor Pages handler method that a request is routed to.
  3. Public properties of a controller or PageModel class, if specified by attributes.

The [BindProperty] attribute can be applied to an individual public property of a controller or PageModel class to cause model binding to target that property:

public class EditModel : PageModel
{
[BindProperty]
public Instructor? Instructor { get; set; }
}






It can also  be applied to a whole controller or PageModel class to tell model binding to target all public properties of the class:

[BindProperties]
public class CreateModel : PageModel
{
}

By default, properties are not bound for HTTP GET requests. Typically, all you need for a GET request is a record ID parameter. The record ID is used to look up the item in the database. 

Therefore, there is no need to bind a property that holds an instance of the model. In scenarios where you do want properties bound to data from GET requests, set the SupportsGet property to true:

[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }



To Be Continued Part-13...


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.