European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core Hosting :: Disposable Types - Properly Disposing Objects

clock October 18, 2021 07:12 by author Peter

Microsoft .NET has been around for 20 years and one thing that is very critical for every to know is exactly how memory management works in the runtime. If you don’t, you will cause performance issues but more serious is causing virtual memory leaks. The way that .NET was designed back in the late ’90s is that it does not have memory leaks in the true sense, but it can create virtual memory leaks.

In a nutshell, if your app has a virtual memory leak, the memory is not destroyed correctly properly, and the leak just keeps building up until the app or service crashes. I have even seen it bring down servers on the backend (I have written about this many times before, so I won’t re-tell them here) and in client apps.
This article covers the way to dispose of objects properly for most cases. There are edge cases where Dispose should not be called due to the lifetime of the object. That will be covered in a separate article.

The reason I decided to write a comprehensive set of articles about reference types that implement IDisposable and where you might need to in your types is because of a recent solution I worked on. Unfortunately, this solution has the most issues of any of the millions of lines of code I have analyzed in the past 20 years. I had hoped that after all this time, developers would know how to do this correctly, but sadly it is obvious to me far too many do not, so I hope these articles will help this critical issue.

This solution has a little over a million lines of code. First, I found over 600 places in the code where Dispose() is not being called on Disposable types. Also, I found over 90 types that either did not implement IDisposable correctly or did not implement it when it needed to. For the classes that did implement IDisposable, not even one did it correctly. These changes will cause over 2,000 touchpoints in the code that will need to be changed, code reviewed, tested, and deployed.

The reason I’m sharing these real-world numbers is that if developers do not deal with these types when the code is first written, it will be very, very expensive and time-consuming to fix later down the road (if they even get fixed). Far too many teams do not understand why they must restart servers or services on a regular basis… this is the reason! Please use these articles as a warning for your team and management!

New Code Rules
I feel so strongly about this I made it the topic of a recent New Code Rules segment on my show Rockin’ the Code World with dotNetDave on C# Corner Live. I rant in this video but also give ideas for Microsoft to once and for all solve this issue so developers do not need to worry about it and so apps and services stop failing.

Two Types of Memory Management in .NET
Microsoft .NET handles memory in two very different ways that every developer needs to fully understand. The first is the memory stack where all value types are created. The second is the memory heap where all reference types are created and managed by the garbage collector, and this will be the focus of this article. How do you know if a type is a value or reference type? It’s fairly easy… all types such as DateTime, integer, Boolean, or any of the framework types that are number-based, plus user-defined types (structures), are value types and live on the memory stack. Everything else, including the classes you create, are reference types and live on the memory heap. Essentially if you create a type by using ‘new’, it’s a reference type, including the string type. Reference types are what needs attention, especially if they implement IDisposable or contain any disposable fields.
The Memory Heap

People have been writing about how the memory heap works in .NET since it was released, so I won’t rehash that here since that would be an article (or an eBook) in itself. If you are new to .NET or don’t fully understand how the memory heap and the Garbage Collector works, go here for more detailed information from Microsoft.

I will quickly mention that the reason .NET is very performant is that when objects are created on the heap, they are always created at the top of the heap. When an object is no longer is used, it is marked to be removed from memory by the Garbage Collector (GC). They do not go away at the end of the code block! Then the heap is compacted by the GC. When are they are removed from memory?

Whenever the Garbage Collector wants to!

Well, it’s a lot more complicated than that, but just remember, developers have no real direct control over the GC. All we can do is allocate cautiously, release objects as soon as possible, and most importantly call Dispose on any disposable objects or implement IDisposable for the types we create that contain a field that is a disposable type. In the early days of .NET, I spent a lot of time watching and learning how the GC works, so I understand it well. Also, twice I had one of the engineers who created the GC speak at the user group I ran for 20 years. Listening to him and speaking with him taught me even more about how memory works in .NET and the pitfalls of the GC.
Disposing Disposable Types

First, let us get into what I teach my beginner students when I taught at a university.

It is critically important to call Dispose() on any type that implements IDisposable!

If a type implements IDisposable it means that it has something it needs to clean up like file handles, memory pointers, other disposable types, and more. So, developers MUST call Dispose as soon as the object is done being used. How do you know if a type implements IDisposable? There are two simple ways.

The first is, just type “.Dispose” at the end of the variable for the type, if it comes up in Intellisense, then you need to call it. The other method is to right mouse click on the type and selects ‘Go to Definition’ and see if IDisposable is in the definition of the class. This is exactly what I tell my beginner students. After you deal with disposable types for a while, you will start to remember which ones are. Here are some helpful tips that I use when I first analyze a codebase.

    If the type name ends in “Stream”, it’s disposable.
    If the type name ends in “Writer” or “Reader”, it’s most likely disposable.
    Any types that deal with graphics are most likely disposable such as the Bitmap type.
    If the type deals with connections, such as databases, sockets, HTTP, it’s disposable. This also includes related types such as DataTable and MailMessage and more.

How we dispose of disposable objects has changed since .NET was created. The safest, recommended way is by using the using pattern and statement.

Here is how to properly use the using statement pattern (the code below is from my OSS called Spargine).
public static TResult Deserialize<TResult>(string xml) where TResult: class
{
    using(var sr = new StringReader(xml))
    {
        var xs = new XmlSerializer(typeof(TResult));
        return (TResult) xs.Deserialize(sr);
    }
}


First, the Disposable object is created in the using statement. When the end of that code block is reached, then Dispose of will be called by the runtime. What happens is that the compiler creates a try/finally block and calls Dispose of in the final as shown in the IL code below.

You can also use the simple using statement as shown below,

using var sr = new StringReader(xml);
var xs = new XmlSerializer(typeof(TResult));
return (TResult) xs.Deserialize(sr);

Both using statements do the same thing, but I tend to prefer the original using statement since for me as a code reviewer, it’s easier for me to spot where it’s being used or isn’t being used.
Hidden Disposable Issues

Other “hidden” disposable issues also need to be considered. Some developers who like to put as much code on one line could run into issues. Here is an example.

public static TResult Deserialize<TResult>(string xml) where TResult: class
{
    var xs = new XmlSerializer(typeof(TResult));
    return (TResult) xs.Deserialize(new StringReader(xml));
}

The issue with this is the final line where a new StringReader is created. StringReader is a disposable type and as you can see, there isn’t a call to Dispose in the code or any use of a using statement. Therefore, code like this will cause memory leaks! I can prove that Dispose is not being called by looking at the IL for this method.


As you can see, there isn’t a call to Dispose in the IL. So, it’s very important to not code Disposable types like this but instead using one of the using statements. I wished that Visual Studio and the compilers would not allow disposable types to be created in this manner.

The takeaway from this article is that it is critically important to make sure all your code is properly disposing of disposable types. Not only could this improve the performance of your apps, but more importantly your apps will be free of virtual memory leaks.

I challenge everyone reading this article to do a critical scan of your codebase NOW to ensure that all your disposable types are being disposed of. I would love to hear how many of these issues you found. Just comment below.

Part 2 of this article will tackle how to properly implement the IDisposable interface for types that you create that have field variables that hold disposable types. Part 3 of this article will discuss how to use tools to help you find these issues in your code.



European ASP.NET Core Hosting :: News Feed System Design

clock October 13, 2021 08:43 by author Peter

News Feed is the constantly updating list of stories in the middle of your home page. It includes status updates, photos, videos, links, app activity, and likes from people, pages, and groups that you follow.

There are two main components in the news feed,

  • Publishing the posts
  • Retrieving the posts

Let’s first concentrate on publishing the post.

Publishing a Post

It is pretty straightforward. You log in to the website/app. Under the post, you write the text that you want to post and hit the submit button. As soon as you click on the submit button, the request sends to the server where it first gets authenticated. The server checks whether the user who has to send the request is a valid user or not. The load balancer is used to distribute the traffic to web servers. The web server sends the request data to the post publisher where it gets saved into the database as well as in the post cache for fast retrieval.

Once the post has been saved into the database successfully. Now it’s time to fan out the post.
Fanout

The process of pushing a post to all the followers is called fanout.

There are two ways we can Fanout a post,
    Fanout Read
    Fanout Write

Fanout Read
When you request for news feed, you create a read request to the system. With fanout read, the read request is fanned out to all your followers to read their posts. The feed is created during the read time. Usually, it pulls recent posts of a user.

Pros
    No need to pre-compute the posts for in-active users.
    The cost of the write operations is low.

Cons
    The time taken to load the feed is more as compare to the Fanout Write.
    It can take a lot of time if a user has many followers.
    You cannot update the user feed on a real-time basis. The user has to request the feeds in case he/she wants to see the latest posts.

Fanout Write
In this case, as soon as the post is published, it gets fanned out to all the friends immediately. Most of the work is done at the time of writing to figure out who will get this post. This significantly reduces the read operations on the system. This approach is not recommended if a user has a large number of followers.

Pros
    The cost of the read operation is low.
    Feed is generated in real-time and pushed to all the friends.
    Displaying the feed is faster as compare to the fanout read because it’s pre-computed.

Cons
    It can take significant time if a user has too many friends.

Hybrid
In this approach, we will take the benefits from both the above approaches (Fanout Read and Write). Allowing the users with a less number of followers to use the Fanout Write model whereas the users with a higher number of followers, a Fanout Read model will be used.
Retrieval

When a user sends a request to retrieve a news feed, it lands on the load balancer which distributes the request to different web servers. The news feed service gets the request from the web servers to fetch the news feed from the cache. The news feed cache returned the post ids for the specific user. User cache returns the user-related info and post cache returns the post-related info. Once everything is computed, we send back the response to the web servers that further deliver the content to the user.


Improvement
Scale the System
As the number of users and posts increases, the current system might now be able to handle the load. So we need to scale the system horizontally. There are different ways we can scale the system. We can use Master-Slave System to separate the read and write operations on the system. We can also use Sharding on the data. We can shard the system based on the feed data and posts. The other improvement we can do is to limit the number of requests that we are getting by implementing the Rate Limiting Module at the webserver level.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.


 



European ASP.NET Core Hosting :: HandleError Action Filter In ASP.NET MVC

clock October 6, 2021 07:33 by author Peter

In this article, you will learn how to handleIn all the software Applications, Exception Handling plays a critical role. An exception can also be thrown during runtime, because of some mathematical calculations, some invalid data, or maybe because of network failure etc. ASP.NET MVC has HandleError Attribute (Action Filter), which provides one of the simplest ways to handle errors. HandleError Attribute has a couple of properties which are useful in handling an exception and help in modifying the default behavior of HandleError Attribute.

ExceptionType: Exception Type specifies the type of an exception. If not specified, then HandleError filter handles all the Exception.

View: Specifies the name of view to display when an exception occurs.

Master: Master specifies the name of the master view.

Order: If more than one HandleError attribute is used, then the order specifies the order of the filters applied. We can set an integer from -1 (Highest Priority) to any positive integer. If no order is specified, then the Order value is -1.

In order to use HandleError Attribute, first, we have to enable Custom Error in web.config file.

Let’s Start,
Create a new ASP.NET MVC Project. errors using HandleError Action Filter in ASP.Net MVC.


Select Empty MVC Template and click OK.


    public class HomeController : Controller  
    {  
            // GET: Home  
            public ActionResult Index()  
            {  
                return View();  
            }  
    }  


Right click on View and click on Add View.
    @{  
        ViewBag.Title = "Index";  
    }  
      
    <h2>Home</h2>  
    @Html.ActionLink("About Us","About","Home")  

I have also added About Action method in HomeController. For demonstration purposes, I will throw an exception on calling About Action Method.
    public ActionResult About()  
    {  
                //Throws an exception for demonstration  
                throw new Exception("Some unknown error encountered!");  
                return View();  
     }  


On clicking About us link, you will see the exception is thrown and Yellow Screen of death appears.


Hackers can easily take advantage of the yellow screen of death, because it shows some valuable/secret code. In order to prevent the Yellow screen of death, we have to add Custom Error in web.config file.
    <system.web>  
        <customErrors mode="On"></customErrors>  
    </system.web>  


Add HandleError Attribute on About Action method of HomeController.
    [HandleError]  
    public ActionResult About()  
    {  
                //Throws an exception for demonstration  
                throw new Exception("Some unknown error encountered!");  
                return View();  
    }  


Add shared folder in Views and then add an Error View (error.cshtml), which will be shown when an exception is thrown.

    @{  
        Layout = "~/Views/Shared/_Layout.cshtml";  
    }  
      
    <h3>An error occurred while processing your request. Please contact the administrator.</h3>  

Preview


We can also declare HandleError attribute on the Controller level as well as on Action method. Declare HandleError attribute on an Action method.


Declare HandleError attribute on the Controller level.


Using View property of HandleError attribute, we can show the specified view on getting unhandled exceptions.
    [HandleError(View = "Error")]  

Adding more than One HandleError attribute

We can control the view to be displayed based upon ExceptionType.
    //If Format Exception thrown then SpecificError View is displayed  
    //If Divide by Zero Exception thrown then Error View is displayed  
    [HandleError(View = "SpecificError", ExceptionType = typeof(FormatException))]  
    [HandleError(Order = 2, View = "Error", ExceptionType = typeof(DivideByZeroException))]  
    public ActionResult About()  
    {  
           //Throws an Exception for demonstration  
           throw new FormatException();  
           return View();  
    }  


In the example shown above, if FormatException Occurs, then it will Show SpecificError.cshtml error view or if DivideByZeroException Exception occurs, then it will show Error.cshtml View.
 
Show Error Details
We can also show error detail on getting an exception. HandleErrorInfo class provides information for handling an error that is thrown by the Action method. HandleErrorInfo has several properties like ActionName, ControllerName, and Exception, which help in getting additional information about the exception.
    [HandleError(View = "DetailedError")]  
    public ActionResult About()  
    {  
           //Throwing an Exception for demonstration  
           throw new DivideByZeroException();  
           return View();  
    }  


In the code, shown above, we set DetailedError View for showing the exception.
    @model System.Web.Mvc.HandleErrorInfo  
      
    @{  
        Layout = "~/Views/Shared/_Layout.cshtml";  
    }  
      

    <h4>Error Details:</h4>  
    <p>Controller Name: @Model.ControllerName</p>  
    <p>Action Name: @Model.ActionName</p>  
    <p>Exception: @Model.Exception</p>  


Preview


Setting HandleError Attribute as a Global Filter
We can register HandleError attribute as a global error handling filter. Open Global.asax file and add the code, given below:
    protected void Application_Start()  
    {  
           AreaRegistration.RegisterAllAreas();  
           GlobalFilters.Filters.Add(new HandleErrorAttribute());  
           RouteConfig.RegisterRoutes(RouteTable.Routes);  
    }  

Now, remove all the HandleError attributes from HomeController, build and run the Application.
 
Handle Errors related to Http Status Code
If we visit the path that doesn’t exist it will throw an HTTP 404 exception.

In order to handle it, first, we have to add an Action Method (NotFound in my case), which will return the NotFound.cshtml view.
    public ActionResult NotFound()  
    {  
           return View();  
    }  

NotFound.cshtml Code
    @{  
        Layout = "~/Views/Shared/_Layout.cshtml";  
    }  
      
    <h4>HTTP 404. The resource you are looking for doesn’t exist or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.</h4>  

Now, open web.config file and add the following line of code:
    <customErrors mode="On">  
          <error statusCode="404" redirect="~/Home/NotFound"/>  
    </customErrors>  


Preview


HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.




European ASP.NET Core Hosting :: Save Request And Response Headers In ASP.NET 5 Core

clock October 4, 2021 07:36 by author Peter

In a typical request-response cycle, the request and response headers contain a lot of additional information. This article talks about how to retrieve them and store them in a database. In this article, we’ll use PostgreSQL as the database and connect to it using dotConnect for PostgreSQL.

To be able to work with the code examples demonstrated in this article, you should have the following installed in your system:
    Visual Studio 2019 Community Edition
    PostgreSQL
    dotConnect for PostgreSQL

Create a new ASP.NET Core 5.0 Project in Visual Studio 2019

Assuming that the necessary software has been installed on your computer, follow the steps outlined below to create a new ASP.NET Core Web API project.

  • First off, open the Visual Studio 2019 IDE
  • Next, click "Create a new project" once the IDE has loaded
  • In the "Create a new project" screen, select “ASP.NET Core Web API” as the project template.
  • Click the "Next" button
  • Specify the project name and location - where it should be stored in your system
  • Optionally, click the "Place solution and project in the same directory" checkbox.
  • Next, click the "Create" button
  • In the "Create a new ASP.NET Core Web Application" dialog window that is shown next, select "API" as the project template.
  • In the “Additional Information” screen, .NET 5.0 is the framework version.
  • You should disable the "Configure for HTTPS" and "Enable Docker Support" options by disabling the respective checkboxes.
  • Since we'll not be using authentication in this example, specify authentication as "No Authentication".
  • Finally, click on the "Create" button to finish the process.

This will create a new ASP.NET Core Web API project in Visual Studio.

Install NuGet Package(s)
To work with dotConnect for PostgreSQL in ASP.NET Core 5, you should install the following package into your project:
Devart.Data.PostgreSQL

You have two options for installing this package: either via the NuGet Package Manager or through the Package Manager Console Window by running the following command.
PM> Install-Package Devart.Data.PostgreSQL

Request and Response Headers in ASP.NET Core
Request headers provide more information about the requested resource or the client who is requesting it. You can take advantage of request headers to add extra information to the HTTP Request.

The response headers contain additional information about the response, such as its location and the server. It is an HTTP header that can only be used in an HTTP response and doesn't have to do anything with the content of the message. To provide more context to the response, you can use response headers like Age, Server, and Location.

Both Request headers and Response headers are represented as a collection of key-value pairs that can be passed back and forward between the client and the server.

Reading Request and Response Headers in ASP.NET Core
You can read request and response headers using the Request and Response properties of the HttpContext class. These properties are of HttpRequest and HttpResponse types respectively.

You can use the following code to retrieve the request headers in ASP.NET:
List < string > AllRequestHeaders = new List < string > ();
var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);


The following code snippet can be used to retrieve all response headers:
List < string > AllResponseHeaders = new List < string > ();
var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);


Building a Middleware to Read Request and Response Headers

A middleware is a software component that processes requests and responds. ASP.Net Core typically has a series of middleware components - these middleware components either process requests or pass them to the next component in the request processing pipeline.

Create a new class in your project's root and name it as RequestResponseHeaderMiddleware. Next, replace the default code with the following:
public class RequestResponseHeadersMiddleware {
    private readonly RequestDelegate _next;
    public RequestResponseHeadersMiddleware(RequestDelegate next) {
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext) {
        await _next.Invoke(httpContext);
    }
}

This is a minimalistic implementation of middleware in ASP.NET Core. However, it doesn’t do anything other than passing the control to the next component in the pipeline.

We need to add the logic of reading requests and response headers. We’ve already written the code in the previous section. Here’s the updated version of our middleware:
public class RequestResponseHeadersMiddleware {
    private readonly RequestDelegate _next;
    public readonly List < string > AllRequestHeaders = new List < string > ();
    public readonly List < string > AllResponseHeaders = new List < string > ();
    public RequestResponseHeadersMiddleware(RequestDelegate next) {
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext) {
        var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllRequestHeaders.AddRange(requestHeaders);
        await this._next.Invoke(httpContext);
        var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllResponseHeaders.AddRange(uniqueResponseHeaders);
        await _next.Invoke(httpContext);
    }
}


Create an Extension Method for the Middleware
We’ll now create an extension method for our middleware to be able to conveniently configure the middleware in the Configure method of the Startup class.

To do this, create a new class named RequestResponseHeadersMiddlewareExtensions in a file called RequestResponseHeadersMiddlewareExtensions.cs with the following code in there:
public static class RequestResponseHeadersMiddlewareExtensions {
    public static IApplicationBuilder UseRequestResponseHeadersMiddleware(this IApplicationBuilder builder) {
        return builder.UseMiddleware < RequestResponseHeadersMiddleware > ();
    }
}


Configure the Middleware in the Startup Class
You can write the following code in the Configure method of the Startup class to enable the custom middleware we have built thus far.
app.UseRequestResponseHeadersMiddleware();

Create the Model
Now create the following class in a file of the same name having an extension .cs. We'll use it to store request and response header values.
public class RequestResponseHeader {
    public string RequestHeader {
        get;
        set;
    }
    public string ResponseHeader {
        get;
        set;
    }
}


Create the DbManager Class
The DbManager class wraps all calls made to the database using dotConnect for Postgresql. It has just one method named Save to persist the request and response header values in the Postgresql database.
public class DbManager {
    private readonly string connectionString = "Some connection string...";
    public int Save(RequestResponseHeader requestResponseHeader) {
        try {
            using(PgSqlConnection pgSqlConnection = new PgSqlConnection(connectionString)) {
                using(PgSqlCommand cmd = new PgSqlCommand()) {
                    cmd.CommandText = "INSERT INTO
                    public.requestresponseheaders " +
                    "(requestheader, responseheader) " + "VALUES (@requestheader, @responseheader)";
                    cmd.Connection = pgSqlConnection;
                    cmd.Parameters.AddWithValue("requestkey", requestResponseHeader.RequestHeader);
                    cmd.Parameters.AddWithValue("responsevalue", requestResponseHeader.ResponseHeader);
                    if (pgSqlConnection.State != System.Data.ConnectionState.Open) pgSqlConnection.Open();
                    return cmd.ExecuteNonQuery();
                }
            }
        } catch {
            throw;
        }
    }
}


Call the Save Method from the Middleware
We’ll now modify the middleware we’ve implemented to store the request and response headers in a PostgreSQL database using dotConnect for PostgreSQL.

You can use the following code snippet to call the Save method of the DbManager class from the middleware we implemented earlier.
for (int index = 0; index < AllRequestHeaders.Count; index++) {
    RequestResponseHeader requestResponseHeader = new
    RequestResponseHeader();
    requestResponseHeader.RequestHeader = AllRequestHeaders[index];
    requestResponseHeader.ResponseHeader = AllResponseHeaders[index];
    dbManager.Save(requestResponseHeader);
}

As you can see here, there are two string collections namely AllRequestHeaders and AllResponseHeaders that hold the request and response header values respectively. We saw how it is done earlier in the article.

In this code snippet, an instance of RequestResponseHeader is created, its properties initialized and then this instance is passed as a parameter to the Save method.

Here is the complete code of the middleware for your reference:
public class RequestResponseHeadersMiddleware {
    private readonly RequestDelegate _next;
    public readonly List < string > AllRequestHeaders = new List < string > ();
    public readonly List < string > AllResponseHeaders = new List < string > ();
    private readonly DbManager dbManager = new DbManager();
    public RequestResponseHeadersMiddleware(RequestDelegate next) {
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext) {
        var requestHeaders = httpContext.Request.Headers.Where(x => AllRequestHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllRequestHeaders.AddRange(requestHeaders);
        await this._next.Invoke(httpContext);
        var uniqueResponseHeaders = httpContext.Response.Headers.Where(x => AllResponseHeaders.All(h => h != x.Key)).Select(x => x.Key);
        AllResponseHeaders.AddRange(uniqueResponseHeaders);
        await _next.Invoke(httpContext);
        for (int index = 0; index < AllRequestHeaders.Count; index++) {
            RequestResponseHeader requestResponseHeader = new
            RequestResponseHeader();
            requestResponseHeader.RequestHeader = AllRequestHeaders[index];
            requestResponseHeader.ResponseHeader = AllResponseHeaders[index];
            dbManager.Save(requestResponseHeader);
        }
    }
}


In ASP.NET Core, you can read request and response headers in your application easily. Request headers allow you to work with optional data that is stored as key-value pairs. Response headers include extra information about the response that allows for a more comprehensive context of the response to be sent to the client.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: HTTPRequest Class In ASP.NET

clock September 29, 2021 08:20 by author Peter

The HttpRequest class is present in the System.Web namespace. During a web request, the HttpRequest class enables ASP.NET to read the HTTP values sent by a client. The method of this class is used to get the path information and save requests on the disk.

Properties and Methods of HTTPRequest Class
Following are some of the important properties of the HttpRequest class

Path
This property retrieves the virtual path of the current request.
public string Path { get; }

Code retrieves the path of the requested URL.
esponse.Write(“Path is :”+Request.Path);

Here Request.Path retrieves the path of the current URL request. The method Response.Write() displays the retrieved path.

PathInfo
This property retrieves the additional path information of the current request. It retrieves the information only for resources that have a URL extension.
Syntax is,
public string PathInfo { get };


Source code
if (Request.PathInfo == String.Empty) {
    Response.Write(”PathInfo property has no info...”);
} else {
    Response.Write(“ < br > PathInfo contains: < br > ”+Request.PathInfo);
}

Here String.Empty represents an empty string. The if condition checks whether PathInfo is empty. If there is no path information of the current request, Response.Write() method displays a message stating that the PathInfo property contains no information. If path information is available, the Request.PathInfo retrieves the path and Response.Write() method displays it on the web page.

UserAgent
This property retrieves the user agent string of the client browser. Consider the following example of a user agent string returned by the UserAgent property.
Mozilla/5.0(Windows;U;Windows NT 5.1; en-IN; rv:1.7.2) Geco/20050915 Firefox/2.0.6

In this example, the user agent string indicates which browser the user is using, its version number, and details about the system such as operating system and version. The web server can use this information to provide content that is defined for a specific browser. Also identifies the user’s browser and provides certain system details to servers.

The syntax for using the UserAgent property is,
public string UserAgent { get; }

For example,
Response.Write(“User Agent is :” +Request.UserAgent);

The code UserAgent property retrieves the user agent string of the client browser for the current URL request. This string is displayed on the web page using the Response.Write() method.

UserHostAddress
This property retrieves the host Internet Protocol (IP) address of the remote client who makes the request.

The IP address is a unique address used to identify a computer on a network. This address helps computers on the network to communicate with each other. 102.169.2.1 is an example of an IP address. The property UserHostAddress is used to retrieve the IP address of the client computer.

The syntax for using the UserHostAddress property is,
public string UserHostAddress { get;}

For example,
Response.Write(“User Host Address is:”+Request.UserHostAddress);

The code Request.UserHostAddress retrieves the host IP address of the remote client making the current URL request. This IP host address is displayed on web page using Response.Write() method.

TotalBytes
This property retrieves the number of bytes in the current input stream. The syntax for using the TotalBytes property is,
public int TotalBytes {get;}

Code below demonstrate the use of the TotalBytes property,
if (Request.TotalBytes > 1000) {
    Response.Write(“The request is 1 KB or greater”);
}

The if condition checks if the total number of bytes in the input stream is greater than 1000. If the condition evaluates to true, Response.Write() method is displays the message “ The request is 1KB or greater” on the web page.

Following are some of the important methods of the HttpRequest class.

BinaryRead()
This method is used to retrieve the data sent to the server from the client.

The syntax is,
public byte[] BinaryRead(int count)

where count represents the number of bytes to be read. Code shows the use of the BinaryRead() method.
int intTotalBytes=Request.TotalBytes;
byte[] bCount=Request.BinaryRead(intTotalBytes);


In this code, intTotalBytes is declared as an integer variable that stores the total number of bytes in the current input stream. This number is retrieved using Request.TotalBytes. This value is then used by the BinaryRead() method to perform a binary read of the input stream and store the data that is read into a byte array named bCount.

GetType()
This method retrieves the type of the current instance.

Syntax
public Type GetType()

Where, Type is the class that represents various type declarations such as class types, array types, and interface types.

For example,
Response.Write(“<br>Type:” +Request.GetType());

The GetType() method retrieves the Type of the instance and it is displayed using the Response.Write() method.

Expectations of HttpRequest Class
Exceptions are runtime errors that occur due to certain problems encountered at the time of execution of code. When working with ASP.NET using C# , exception handling is achieved using the try-catch-finally construct. The try block encloses the statements that might throw an exception and the catch block handles the exception. The code is finally block is always executed, regardless of whether an exception occurred or not, and this code contains cleanup routines for exception situations.

When calling the BinaryRead() method of the HttpRequest class, an exception of type ArgumentException can possibly occur. This exception occurs when calling a method, if at least one of the arguments passed to the method does not meet the parameter specification.

The Path property of the HttpRequest class retrieves the virtual path of the current request. The UserHostAddress property of HttpRequest class retrieves the host IP address of the remote client making the request. GetType() also retrieves the type of the current instance.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: How To Upgrade ASP.NET Core 2.1 To ASP.NET Core 3.1 version?

clock September 28, 2021 07:34 by author Peter

This article provides the guidelines to upgrade ASP.NET Core 2.1/2.0 (or lower versions) to 3.1. .Net Core 3.1 has long-term support and if you are using a 2.0/2.1 or lower .NET Core application and need to upgrade it, this write-up will help you. The very first step for migration is changing the target framework. For this: right-click on Project-> properties and then in project properties select the target framework to 3.1. Alternatively, you can change the target framework from .csproj file changing the target framework to netcoreapp3.1.

Right-click on the project and then click on Edit project file.

Then change the target framework to netcoreapp3.1.

Once you change the .net core version from 2.1 to 3.1 from Solution properties, then build the solution. Some packages will be restored and upgraded automatically. You may get number of errors in the solution but with that, there will be some suggestions showing what you need to do after upgrading the solution framework. Based on the suggestion, you can resolve the issue; however, in this article basically, we will discuss the Startup. cs file changes which are very crucial, and will throw errors even if you have no errors after building the solution too.

Guideline 1
You may get the below error while running the application even if your solution builds successfully.

When we continue to run the project, the page will be loaded with the below error message.

Let’s move to the solution of the above error. Thing is after migration to ASP.NET Core 3.1, we have to use UseEndPoints() instead of UseMVC();

Inside Configuration() method of Startup.cs file, we need to change the below code.
app.UseMvc(routes => {
    routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
});

To
app.UseEndpoints(endpoints => {
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});


Guideline 2
You may get the below error,
Error: EndpointRoutingMiddleware matches endpoints setup by EndpointMiddleware and so must be added to the request execution pipeline before EndpointMiddleware

If you get an error like the above then, follow the below suggestion.
We have to use app.UseRouting(); inside the Configuration() method of Startup.cs file
app.UseRouting();//error message suggested to implement this


Guideline 3
Additionally, If you have implemented SignalR then you will get information or warning messages like this :

In ASP.NET Core 2.1 application, SignalR is written as shown below which resides inside the Configuration() method of Startup.cs file.
app.UseSignalR(routes => {
routes.MapHub < ChatUpdaterHub > ("/chat-updater");
});

However, in ASP.NET Core 3.1 it should be implemented with endpoints as illustrated in the below code.
app.UseEndpoints(endpoints => {
endpoints.MapHub < ChatUpdaterHub > ("/chat-updater"); //Signal R implementation
endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});

Code of Startup.cs class of .NET Core 2.1 is
public class Startup {
public IConfiguration Configuration {
    get;
}
public Startup(IConfiguration configuration) {
    this.Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services) {
    services.AddSingleton(defaultEndpointsSettings);
    services.AddDistributedMemoryCache();
    services.AddTransient < ApiRequester > ();
    services.AddHostedService < FetchingBackgroundService > ();
    services.AddMvc();
    services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
    if (env.IsDevelopment()) {
        app.UseDeveloperExceptionPage();
    } else {
        app.UseExceptionHandler("/Home/Error");
    }
    var cachePeriod = env.IsDevelopment() ? "600" : "604800";
    app.UseStaticFiles(new StaticFileOptions {
        OnPrepareResponse = ctx => {
            ctx.Context.Response.Headers.Append("Cache-Control", $ "public, max-age={cachePeriod}");
        }
    });
    app.UseSignalR(routes => {
        routes.MapHub < DataUpdaterHub > ("/ws-updater");
    });
    app.UseMvc(routes => {
        routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
    });
}
}


When we upgrade the same project to .Net Core 3.1 Startup.cs class should be like this,
public class Startup
{
   public IConfiguration Configuration { get; }
   public IWebHostEnvironment Environment { get; }
   public Startup(IConfiguration configuration, IWebHostEnvironment environment)
   {
       this.Configuration = configuration;
       Environment = environment;
   }

   public void ConfigureServices(IServiceCollection services)
   {

       services.AddSingleton(defaultEndpointsSettings);
       services.AddDistributedMemoryCache();
       services.AddTransient<ApiRequester>();
       services.AddHostedService<FetchingBackgroundService>();
       services.AddMvc();
       services.AddSignalR();

   }

   public void Configure(IApplicationBuilder app)
   {
       if (Environment.IsDevelopment())
       {
           app.UseDeveloperExceptionPage();
       }
       else
       {
           app.UseExceptionHandler("/Home/Error");
       }

       var cachePeriod = Environment.IsDevelopment() ? "600" : "604800";
       app.UseStaticFiles(new StaticFileOptions
       {
           OnPrepareResponse = ctx =>
           {
               ctx.Context.Response.Headers.Append("Cache-Control", $"public, max-age={cachePeriod}");
           }
       });
       app.UseRouting();

       app.UseEndpoints(endpoints =>
       {
           endpoints.MapHub<DataUpdaterHub>("/ws-updater");
           endpoints.MapControllerRoute(
               name: "default",
               pattern: "{controller=Home}/{action=Index}/{id?}");
       });
   }
}

Microsoft Recommendation
Microsoft’s recommendation for migration to .NET Core 3.1 is:
Add UseRouting()
Sequence of UseStatisFiles(), UseRouting(), UseAuthentication() and UseAuthorization(), UseCors() and UseEndPoints() should be in following order

This article described the guidelines to upgrade the .NET Core from 2.1 (or lower versions) to 3.1 with sample code and examples of errors and how to resolve them. I hope it will help you to update your application from lower framework to upper with long-term support.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core Hosting :: Create ASP.NET Core Web API With Entity Framework Code First Approach

clock September 27, 2021 08:28 by author Peter

In this article, we are going to create WEB API in ASP.Net core using Entity Framework Core’s Code first approach. In this, we are creating a simple CRUD operation of employees and test it using Swagger. In this API we are not going to use authentication, we will add this in my upcoming articles.
In this article,

    Create ASP.Net Core Web API Project
    Add Entity Framework and Create Tables
    Create Service to perform CRUD Operation
    Implement Service in Controller
    Test API Using Swagger

Create ASP.Net Core Web API Project
Step 1
Open Visual Studio and create a new project. Here I am using Visual Studio 2019. You can use as per your system and requirements.

Step 2
Find and select Asp.Net Core Web API and then click on the Next button.

Step 3
In the next wizard, you have to enter the following things and then click on the Next button
    Project Name
    Location of your project (Path where you want to save your project)

Step 4
In this wizard screen, you have to specify the following things and then click on create button.

  • Target Framework, here I am using the current version installed in my system which is 5.
  • Authentication type: Currently in this project, we are not using authentication so here I select none.
  • Configure HTTPS: If you host your API with a secure HTTPS connection then you can check this box. It will add a redirection in your project which helps to redirect the http request to HTTPS automatically.
  • Enable Docker: For this project, we are not using docker so leave unchecked
  • Enable Open AI Support: If you want to implement Swagger in your project then you have to check this box. In this project, we are going to use a swagger so I check this box.

 

Now your project is created and you can see the project structure in the below image. Remove extra files like weather controller and model if you don’t want it.

Add Entity Framework and Create Tables
For using the Entity Framework in our project and create a table using the code first approach we have to follow the below steps.

Step 1
Right-click on the project name and click on Manage NuGet Packages.

 

 

Step 2
Install the Following NuGet Packages.

Microsoft.EntityFrameworkCore.SqlServer: This package is used to interact with SQL Server from our C# and .Net Core.
Microsoft.EntityFrameworkCore.Tools: This package is contained various commands like Add-Migration, Drop-Database, Get-DbContext, Get-Migration, Remove-Migration, Scaffold-DbContext, Script-Migration, Update-Database. In this article, we use Add-Migration and Update-Database commands.
Microsoft.Extensions.Configuration: Using this NuGet package we can read data from our app setting file. We will get our connection string from the app setting file.

Step 3

Now we add a new folder in our solution to contain various classes. For adding a new folder in our solution right click on project name the click on Add then click on New Folder and gave the name as Models.

Step 4
In this Models folder, we will use our entity classes. Right-click in this folder then Add then Class. Give a suitable name for your class.

Step 5
Add fields as you want to create in your table. Here I create an Employee class with the following fields. Here key attribute defines that use this column as the primary key.

public class Employees {
    [Key]
    public int EmployeeId {
        get;
        set;
    }
    public string EmployeeFirstName {
        get;
        set;
    }
    public string EmployeeLastName {
        get;
        set;
    }
    public decimal Salary {
        get;
        set;
    }
    public string Designation {
        get;
        set;
    }
}

Step 6
Now we create a context class which use as a middleware to SQL Server. Add a new class in your Models folder and add constructor and Employee DbSet as seen below code.

public class EmpContext: DbContext {
    public EmpContext(DbContextOptions options): base(options) {}
    DbSet < Employees > Employees {
        get;
        set;
    }
}

Step 7
Now we have to connect SQL Server with our project, for that, we need a connection string, and for this string, we are going to add the in-app setting file. Add your connection string as showing below.

As see in the above code here I pass. (dot) as a server name because I used my local SQL Server. Then gave database name Tutorial, if this database does not exist then it will generate automatically. Here I have not given any username and password because I use windows authentication for this. If you want to use another method to login then pass username and password.

Step 8
Now we have to add Db Context in our startup file for this open startup file and add the following code.

services.AddDbContext<EmpContext>(x => x.UseSqlServer(Configuration.GetConnectionString("ConStr")));

In ConfigureService Method, we add our EmpContext class and pass connection string in it by getting from our appsetting file using Configure.GetConnectionString() method.

Step 9
Now open Package Manager Console by click on Tool Menu then NuGet Package Manager then Package Manager Console.


Step 10
Add the following command.

    Add-Migration Init

Here Init is our name of migration, you can give as per your choice. Hit enter.

Step 11
As you can see in your solution new folder named Migration is created and in this project, there are two files. One is EmpContextModelSnapshot and another one is *_Init, here * mean date time stamp.

Step 12
For now, our database and table are not created to make changes in the Server-side use below command.
    Update-Database

Now you can see in our SQL Server Employee table is created with the same fields as we add in our model.


Create New Response Model
To save and delete we are going to return a new model for send data to the user. To create a new folder called ViewModels In your solution because we want to store Entity classes and Other classes in a different place. Add a new class Called ResponseModel in this folder with the following properties as seen below code.

public class ResponseModel {
    public bool IsSuccess {
        get;
        set;
    }
    public string Messsage {
        get;
        set;
    }
}



European ASP.NET Core Hosting :: Hidden IDisposable Issues in Microsoft .NET

clock September 24, 2021 07:41 by author Peter

As an experienced .NET software engineer, whenever I am hired into a new team, I almost immediately get tasked to fix coding issues. I guess since I am dotNetDave and I wrote the only coding standards book for .NET. Out of all the millions of lines of code I have reviewed in the past 20 years of .NET, hands down the one issue are developers not properly disposing of objects that implement IDisposable. In some teams, it has taken me many months of hard work to fix these issues that will always lead to virtual memory leaks.

The problem I am seeing is that I see a lot of code like this:
public static TResult Deserialize<TResult>(string xml) where TResult : class
{
var xs = new XmlSerializer(typeof(TResult));
return (TResult)xs.Deserialize(new StringReader(xml));
}

The issue with this is the final line where a new StringReader is created. StringReader (and just about every type that ends in ‘Reader’) is one of those types that implement IDisposable to clean up the memory it uses. Since it does, it’s extremely important that the developer call .Dispose when it’s no longer needed or use the using code block.

I can prove that Dispose is not being called by looking at the IL for this method.

As you can see, there isn’t a call to Dispose in the IL.

The Solution

The following code, from my Spargine open-source project, properly codes this method as shown below:

public static TResult Deserialize<TResult>(string xml) where TResult : class
{
using var sr = new StringReader(xml);
var xs = new XmlSerializer(typeof(TResult));

return (TResult)xs.Deserialize(sr);
}

As you can see, this uses the new way of implementing the using code statement. This means that at the end of the code block, in this case the method, Dispose will be called on StringReader, and its memory will be cleaned up. Want proof? Here it is:

As you can see, a try/finally is created by the compiler and in the finally Dispose is being called. This should be the only way to code types that implement IDisposable and not the way that was first shown. Since these issues have been around ever since .NET was created, I wished Visual Studio would alert the coder that they are causing a memory leak! Until then, be careful or hire me to help your team!

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: Send Push Notification To Android Device From .Net Core Web API

clock September 20, 2021 07:23 by author Peter

In this article, you will learn about how to send push notifications to android devices using FCM from .Net Core Web API.  You will also learn how to create a Firebase project and get Server Key and Sender ID step by step. Our main focus is how to handle send notification functionality on the API side.
What is FCM?

Firebase Cloud Messaging (FCM) is a free cloud service from Google that allows users to send notifications and messages to users.

It is a cross-platform messaging solution. You can send notifications and messages across a variety of platforms, including Android, iOS and web applications.
Create Firebase Project

Go to Firebase Console.

Follow the steps to set up the project.
After adding the project to the Firebase, add App to the same project.
Send Push Notification To Android Device From .Net Core Web API

Enter package name, app name, and SHA-1 key of your Android Studio project. Follow all the steps to complete the add Firebase to your Android app. If you face any problem, you can refer to  Add Firebase to your Android Project.

Get FCM Sender ID & Server Key
Click on the “Gear” icon and access “Project settings”.

Go to the “Cloud Messaging” section and you will have access to the Sender ID and Server Key. We will use it later in the API.

For setting up a Firebase Cloud Messaging client app on Android and getting FCM registration token or device token please refer to this Set up an Android client.
How to send FCM push notification from an ASP.NET Core Web API project.

What CorePush Package?

It’s very Lightweight .NET Core Push Notifications for Android and iOS. I used it in my project to send Firebase Android and Apple iOS push notifications. In this article just I focus on sending push notifications on Android devices Useful links,

  • NuGet package
  • Documentation

Step 1 – Create Project
Open Visual Studio click on “Create a new project”.

Select ASP.NET Core Web Application option.

Add Project name and Solution name.

Select the “API” option with “.NET Core” and “ASP.NET Core 3.1” to create ASP.NET API.


You can see the default folder structure.

Step 2 – Install NuGet Packages
Open Package Manager Console


And run the below commands one by one:

  1. Install-Package CorePush
  2. Install-Package Newtonsoft.Json
  3. Install-Package Swashbuckle.AspNetCore

Step 3 – Create Models for the controller
Now, create a directory with name Models and add the following files

  • ResponseModel.cs
  • NotificationModel.cs
  • FcmNotificationSetting.cs

ResponseModel.cs will contain definitions for response models.
NotificationModel.cs will contain definitions for notification and google notification model
FcmNotificationSetting.cs will contain definitions for FCM notification settings.

Code for ResponseModel.cs file,
using Newtonsoft.Json;

namespace net_core_api_push_notification_demo.Models
{
    public class ResponseModel
    {
        [JsonProperty("isSuccess")]
        public bool IsSuccess { get; set; }
        [JsonProperty("message")]
        public string Message { get; set; }
    }
}


Code for NotificationModel.cs file,
using Newtonsoft.Json;

namespace net_core_api_push_notification_demo.Models
{
    public class NotificationModel
    {
        [JsonProperty("deviceId")]
        public string DeviceId { get; set; }
        [JsonProperty("isAndroiodDevice")]
        public bool IsAndroiodDevice { get; set; }
        [JsonProperty("title")]
        public string Title { get; set; }
        [JsonProperty("body")]
        public string Body { get; set; }
    }

    public class GoogleNotification
    {
        public class DataPayload
        {
            [JsonProperty("title")]
            public string Title { get; set; }
            [JsonProperty("body")]
            public string Body { get; set; }
        }
        [JsonProperty("priority")]
        public string Priority { get; set; } = "high";
        [JsonProperty("data")]
        public DataPayload Data { get; set; }
        [JsonProperty("notification")]
        public DataPayload Notification { get; set; }
    }
}


Code for FcmNotificationSetting.cs file,
namespace net_core_api_push_notification_demo.Models
{
    public class FcmNotificationSetting
    {
        public string SenderId { get; set; }
        public string ServerKey { get; set; }
    }
}


Step 4 – Update appsettings.Development.json file

Code for appsettings.Development.json file,

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "FcmNotification": {
    "SenderId": "*SENDER_ID*",
    "ServerKey": "*SERVER_KEY*"
  }
}

Replace *SENDER_ID* with your sender Id.
Replace *SERVER_KEY* with your server key.
Which we have found from the Cloud Messaging section of Firebase project settings.

Step 5 – Create Service
Now, create a directory with the name Services and add the following file.
Code for NotificationService.cs file,
using CorePush.Google;
using Microsoft.Extensions.Options;
using net_core_api_push_notification_demo.Models;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using static net_core_api_push_notification_demo.Models.GoogleNotification;

namespace net_core_api_push_notification_demo.Services
{
    public interface INotificationService
    {
        Task<ResponseModel> SendNotification(NotificationModel notificationModel);
    }

    public class NotificationService : INotificationService
    {
        private readonly FcmNotificationSetting _fcmNotificationSetting;
        public NotificationService(IOptions<FcmNotificationSetting> settings)
        {
            _fcmNotificationSetting = settings.Value;
        }

        public async Task<ResponseModel> SendNotification(NotificationModel notificationModel)
        {
            ResponseModel response = new ResponseModel();
            try
            {
                if (notificationModel.IsAndroiodDevice)
                {
                    /* FCM Sender (Android Device) */
                    FcmSettings settings = new FcmSettings()
                    {
                        SenderId = _fcmNotificationSetting.SenderId,
                        ServerKey = _fcmNotificationSetting.ServerKey
                    };
                    HttpClient httpClient = new HttpClient();

                    string authorizationKey = string.Format("keyy={0}", settings.ServerKey);
                    string deviceToken = notificationModel.DeviceId;

                    httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", authorizationKey);
                    httpClient.DefaultRequestHeaders.Accept
                            .Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    DataPayload dataPayload = new DataPayload();
                    dataPayload.Title = notificationModel.Title;
                    dataPayload.Body = notificationModel.Body;

                    GoogleNotification notification = new GoogleNotification();
                    notification.Data = dataPayload;
                    notification.Notification = dataPayload;

                    var fcm = new FcmSender(settings, httpClient);
                    var fcmSendResponse = await fcm.SendAsync(deviceToken, notification);

                    if (fcmSendResponse.IsSuccess()) {
                        response.IsSuccess = true;
                        response.Message = "Notification sent successfully";
                        return response;
                    } else {
                        response.IsSuccess = false;
                        response.Message = fcmSendResponse.Results[0].Error;
                        return response;
                    }
                }
                else {
                    /* Code here for APN Sender (iOS Device) */
                    //var apn = new ApnSender(apnSettings, httpClient);
                    //await apn.SendAsync(notification, deviceToken);
                }
                return response;
            }
            catch (Exception ex) {
                response.IsSuccess = false;
                response.Message = "Something went wrong";
                return response;
            }
        }
    }
}

Step 6 – Update Startup.cs file
Code for Startup.cs file,

using CorePush.Apple;
using CorePush.Google;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using net_core_api_push_notification_demo.Models;
using net_core_api_push_notification_demo.Services;

namespace net_core_api_push_notification_demo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddTransient<INotificationService, NotificationService>();
            services.AddHttpClient<FcmSender>();
            services.AddHttpClient<ApnSender>();

            // Configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("FcmNotification");
            services.Configure<FcmNotificationSetting>(appSettingsSection);

            // Register the swagger generator
            services.AddSwaggerGen(c => {
                c.SwaggerDoc(name: "V1", new OpenApiInfo { Title = "My API", Version = "V1" });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment()) {
                app.UseDeveloperExceptionPage();
            }

            // Enable middleware to serve generated Swagger as a JSON endpoint
            app.UseSwagger();
            // Enable the SwaggerUI
            app.UseSwaggerUI(c => {
                c.SwaggerEndpoint(url: "/swagger/V1/swagger.json", name: "My API V1");
            });

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => {
                endpoints.MapControllers();
            });
        }
    }
}

Step 7 – Add Controller
Now, add the NotificationController.cs file in the Controllers folder
Code for NotificationController.cs file,

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using net_core_api_push_notification_demo.Models;
using net_core_api_push_notification_demo.Services;

namespace net_core_api_push_notification_demo.Controllers
{
    [Route("api/notification")]
    [ApiController]
    public class NotificationController : ControllerBase
    {
        private readonly INotificationService _notificationService;
        public NotificationController(INotificationService notificationService)
        {
            _notificationService = notificationService;
        }

        [Route("send")]
        [HttpPost]
        public async Task<IActionResult> SendNotification(NotificationModel notificationModel)
        {
            var result = await _notificationService.SendNotification(notificationModel);
            return Ok(result);
        }
    }
}

Step 8 – Running Web API
Now, press F5 to start debugging the Web API project, if everything is OK, we’ll get the following output in the browser.


Now, we will call the send notification API and check whether the notification is sent or not. As per the below screenshot, enter all properties details and hit the Execute button. If everything is fine, then the value of isSuccess property is true and the value of the message property is “Notification sent successfully”.

Wow, here is the notification!



European ASP.NET Core Hosting :: .NET 6 RC 1 Released

clock September 17, 2021 08:45 by author Peter

Microsoft has released .NET 6 RC 1, the first of two “go live” RC releases that are supported in production.

.NET 6 Release Candidate 1 has been tested and is supported with Visual Studio 2022 Preview 4. VS 2022 allows users to leverage the Visual Studio tools developed for .NET 6 like development in .NET MAUI, new Web Live Preview for WebForms, Hot Reload for C# apps, and other performance improvements in the IDE experience.

Microsoft said that for the last month or so, the .NET team has been focused exclusively on quality improvements that resolve functional or performance issues in new features or regressions in existing ones. RC 1 release doesn't focus on new goodies, but rather foundational features of .NET 6. Some of these features won't be fully realized for a while.

Talking about the foundational features in .NET 6, Microsoft wrote "In each release, we take on a few projects that take multiple years to complete and that do not deliver their full value for some time. Given that these features have not come to their full fruition, you’ll notice a bias in this post to what we’re likely to do with these features in .NET 7 and beyond."

Some of such features include Source build, Profile-guided optimization (PGO), Dynamic PGO, Crossgen2, Security mitigations, and SDK workloads.

Microsft revealed that it is very close to delivering a fully automated version of Source build, which is a scenario and also infrastructure. The deliverable for source build is a source tarball. The source tarball contains all the source for a SDK, and from there, Red Hat or another organization can build their own version of the SDK. In the Linux ecosystem both source and binary packages or tarballs are required for a given component. .NET already had binary tarballs available and now have source tarballs as well.

Profile Guided Optimization (PGO) is an important capability of most developer platforms. It improves the performance of applications by adding new information to the optimization process that is dependent on how the application executes, not just on the program's code. With .NET 6, Microsoft has rebuild the PGO system from scratch. This was motivated in large part by crossgen2 as the new enabling technology. The runtime libraries are compiled to ready-to-run format optimized with (the new form of) PGO data. This is all enabled with crossgen2. Currently, the team has not enabled anyone else to use PGO to optimize apps. That’s what will be coming next with .NET 7.

Dynamic PGO is the mirror image of the static PGO. Simliler to static PGO which is integrated with crossgen2, dynamic PGO is integrated with RyuJIT. Dynamic PGO is automatic and uses the running application to collect relevant data. This data is lost after every application run. Dynamic PGO is similar to a tracing JIT. With dynamic PGO the JIT can now do further instrumentation during tier 0, to track not just call counts but all of the interesting data it can use for profile-guided optimization, and then it can employ that during the compilation of tier 1.

Crossgen2 replaces crossgen: With this release, Crossgen2 has been enabled for all existing crossgen scenarios, and the .NET team has also removed (the old) crossgen from the SDK, making it no longer accessible and unable to be used. "Crossgen (1 and 2) enables pre-compiling IL to native code as a publishing step. Pre-compilation is primarily beneficial for improving startup. Crossgen2 is a from-scratch implementation that is already proving to be a superior platform for code generation innovation. For example, crossgen2 can generate code for a broader set of IL patterns than crossgen1."

The release adds preview support for two key security mitigations CET, and W^X. These will be enabled by default in .NET 7.

Control-flow Enforcement Technology (CET) from Intel is a security feature available, in some latest Intel and AMD processors, adds potential to the hardware that protect against some common types of attacks involving control-flow hijacking. CET shadow stacks enables the processor and operating system to track the control flow of calls and returns in a thread in the shadow stack in addition to the data stack, and detect unintended changes to the control flow. W^X blocks the simplest attack path by disallowing memory pages to be writeable and executable at the same time. It is available all operating systems with .NET 6 but only enabled by default on Apple Silicon. It will be enabled on all operating systems for .NET 7.

HostForLIFE.eu ASP.NET Core Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in