European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

ASP.NET 5 Hosting Available NOW!

clock November 24, 2020 08:08 by author Scott

HostForLIFE.eu is a popular online Windows and ASP.NET based hosting service provider catering to those people who face such issues. The company has managed to build a strong client base in a very short period of time. It is known for offering ultra-fast, fully-managed and secured services in the competitive market.

.NET 5 is the next version of .NET Core and the future of the .NET platform. With .NET 5 you have everything you need to build rich, interactive front end web UI and powerful backend services. .NET 5 contains great performance improvements in the
runtime and libraries and for the gRPC components. These improvements, when applied to ASP.NET Core, result in some significant wins in throughput (RPS) and latency.

HostForLIFE.eu hosts its servers in top rate data centers that's located in Amsterdam (NL), London (UK), Washington, D.C. (US), Paris (France), Frankfurt (Germany), Chennai (India), Milan (Italy), Toronto (Canada) and São Paulo (Brazil) to ensure 99.9% network period. All data center feature redundancies in network connectivity, power, HVAC, security, and fire suppression. HostForLIFE.eu proudly announces available ASP.NET 5 feature for new customers and existing customers. 

HostForLIFE.eu is a popular online Windows based hosting service provider catering to those people who face such issues. The company has managed to build a strong client base in a very short period of time. It is known for offering ultra-fast, fully-managed and secured services in the competitive market. Their powerful servers are especially optimized and ensure ASP.NET 5 performance. They have best data centers on three continent, unique account isolation for security, and 24/7 proactive uptime monitoring.

Further information and the full range of features ASP.NET 5 Hosting can be viewed here
https://hostforlife.eu/European-ASPNET-5-Hosting.

 



European ASP.NET Core Hosting - HostForLIFE.eu :: Know Further About ASP.NET Core Endpoint Routing

clock January 29, 2020 08:49 by author Scott

Introduction

In this post I will explain the new Endpoint Routing feature that has been added to the ASP.NET Core middleware pipeline starting with version 2.2 and how it is evolving through to the upcoming version 3.0 that is at preview 3 at present time.

The motivation behind endpoint routing

Prior to endpoint routing the routing resolution for an ASP.NET Core application was done in the ASP.NET Core MVC middleware at the end of the HTTP request processing pipeline. This meant that route information, such as what controller action would be executed, was not available to middleware that processed the request before the MVC middleware in the middleware pipeline.

It is particularly useful to have this route information available for example in a CORS or authorization middleware to use the information as a factor in the authorization process.

Endpoint routing also allows us to decouple the route matching logic from the MVC middleware, moving it into its own middleware. It allows the MVC middleware to focus on its responsibility of dispatching the request to the particular controller action method that is resolved by the endpoint routing middleware.

The new Endpoint Routing middleware

Due to the above mentioned reasons, the endpoint routing feature was born to allow the route resolution to happen earlier in the pipeline in a separate endpoint routing middleware. This new middleware can be placed at any point in the pipeline after which other middleware in the pipeline can access the resolved route data.

The endpoint routing middleware API is evolving with the upcoming 3.0 version of the .NET Core framework. For that reason, the API that I will describe in the following sections may not be the final version of the feature. However the over all concept and understanding of how route resolution and dispatch work using endpoint routing should still apply.

In the following sections I will walk you through the current iterations of endpoint routing implementation from version 2.2 to version 3.0 preview 3, then I will note some changes that are coming based on the current ASP.NET Core source code.

The three core concepts involved in Endpoint Routing

There are three overall concepts that you need to understand to be able to understand how endpoint routing works.

These are the following:

  • Endpoint route resolution
  • Endpoint dispatch
  • Endpoint route mapping

Endpoint route resolution

The endpoint route resolution is the concept of looking at the incoming request and mapping the request to an endpoint using route mappings. An endpoint represents the controller action that the incoming request resolves to, along with other metadata attached to the route that matches the request.

The job of the route resolution middleware is to construct and Endpoint object using the route information from the route that it resolves based on the route mappings. The middleware then places that object into the http context where other middleware the come after the endpoint routing middleware in the pipeline can access the endpoint object and use the route information within.

Prior to endpoint routing, route resolution was done in the MVC middleware at the end of the middleware pipeline. The current 2.2 version of the framework adds a new endpoint route resolution middleware that can be placed at any point in the pipeline, but keeps the endpoint dispatch in the MVC middleware. This will change in the 3.0 version where the endpoint dispatch will happen in a separate endpoint dispatch middleware that will replace the MVC middleware.

Endpoint dispatch

Endpoint dispatch is the process of invoking the controller action method that corresponds to the endpoint that was resolved by the endpoint routing middleware.

The endpoint dispatch middleware is the last middleware in the pipeline that grabs the endpoint object from the http context and dispatches to particular controller action that the resolved endpoint specifies.

Currently in version 2.2 dispatching to the action method is done in the MVC middleware at the end of the pipeline.

In the version 3.0 preview 3, the MVC middleware is removed. Instead the endpoint dispatch happens at the end of the middleware pipeline by default. Because the MVC middleware is removed, the route map configuration that is usually passed to the MVC middleware, is instead passed to the endpoint route resolution middleware.

Based on the current source code, the upcoming 3.0 final release should have a new endpoint routing middleware that is placed at the end of the pipeline to make the endpoint dispatch explicit again. The route map configuration will be passed to this new middleware instead of the endpoint route resolution middleware as it is in version 3 preview 3.

Endpoint route mapping

When we define route middleware we can optionally pass in a lambda function that contains route mappings that override the default route mapping that ASP.NET Core MVC middleware extension method specifies.

Route mappings are used by the route resolution process to match the incoming request parameters to a route specified in the rout map.

With the new endpoint routing feature the ASP.NET Core team had to decide which middleware, the endpoint resolution or the endpoint dispatch middleware, should get the route mapping configuration lambda as a parameter.

In fact this is the part of the endpoint routing where the API is in flux. As I write this post, the route mapping is being moved from the route resolution middleware to the endpoint dispatcher middleware.

I will show you the route mapping API in version 3 preview 3 first, then show you the latest route mapping API in the ASP.NET Core source code. In the source code version, we will see that the route mapping is moved to the endpoint dispatcher middleware extension method.

Its important to note that the endpoint resolution happens during runtime request handling after the route mapping is setup during application startup configuration. Therefor the route resolution middleware has access to the route mappings during request handling regardless of which middleware the route map configuration is passed to. 

Accessing the resolved endpoint

Any Middleware after the endpoint route resolution middleware will be able to access the resolved endpoint through the HttpContext.

The following code snippet shows how this can be done in your own middleware:

//our custom middleware
app.Use((context, next) =>
{
    var endpointFeature = context.Features[typeof(Microsoft.AspNetCore.Http.Features.IEndpointFeature)]
                                           as Microsoft.AspNetCore.Http.Features.IEndpointFeature;

    Microsoft.AspNetCore.Http.Endpoint endpoint = endpointFeature?.Endpoint;

    //Note: endpoint will be null, if there was no
    //route match found for the request by the endpoint route resolver middleware
    if (endpoint != null)
    {
        var routePattern = (endpoint as Microsoft.AspNetCore.Routing.RouteEndpoint)?.RoutePattern
                                                                                   ?.RawText;

        Console.WriteLine("Name: " + endpoint.DisplayName);
        Console.WriteLine($"Route Pattern: {routePattern}");
        Console.WriteLine("Metadata Types: " + string.Join(", ", endpoint.Metadata));
    }
    return next();
});

As you can see I am accessing the resolved endpoint object through the IEndpointFeature or the Http Context. The framework provides wrapper methods to access the endpoint object without having to reach directly into the context as I have shown here.

Endpoint routing configuration

The middleware pipeline endpoint route resolver middleware, endpoint dispatcher middleware and endpoint route mapping lambda is setup in the Startup.Configure method of the Startup.cs file of ASP.NET Core project.

This configuration changed between 2.2 and 3.0 preview 3 versions and is still changing before the 3.0 release version. So in order to demonstrate the endpoint routing configuration I am going to declare the general form of the endpoint routing middleware configuration as pseudo code based on the three core concepts listed above:

//psuedocode that passes route map to endpoint resolver middleware
public void Configure(IApplicationBuilder app
                     , IHostingEnvironment env)
{
    //middleware configured before the UseEndpointRouteResolverMiddleware middleware
    //that does not have access to the endpoint object
    app.UseBeforeEndpointResolutionMiddleware();

    //middleware that inspects the incoming request, resolves a match to the route map
    //and stores the resolved endpoint object into the httpcontext
    app.UseEndpointRouteResolverMiddleware(routes =>
    {
        //This is the route mapping configuration passed to the endpoint resolver middleware
        routes.MapControllers();
    })

    //middleware after configured after the UseEndpointRouteResolverMiddleware middleware
    //that can access to the endpoint object
    app.UseAfterEndpointResolutionMiddleware();

    //The middleware at the end of the pipeline that dispatches the controler action method
    //will replace the current MVC middleware
    app.UseEndpointDispatcherMiddleware();
}

This version of our pseudo code shows the route mappings lambda passed as a parameter to the UseEndpointRouteResolverMiddleware endpoint route resolution middleware extension method.

An alternate version that matches what the current source code looks like, is shown below:

//psuedocode version 2 that passes route map to endpoint dispatch middleware
public void Configure(IApplicationBuilder app
                     , IHostingEnvironment env)
{
    app.UseBeforeEndpointResolutionMiddleware()

    //This is the endpoint route resolver middleware
    app.UseEndpointRouteResolverMiddleware();

    //This middleware can access the resolved endpoint object via HttpContext
    app.UseAfterEndpointResolutionMiddleware();

    //This is the endpoint dispatch middleware
    app.UseEndpointDispatcherMiddleware(routes =>
    {
        //This is the route mapping configuration passed to the endpoint dispatch middleware
        routes.MapControllers();
    });
}

In this version the route mapping configuration is passed as a parameter to the endpoint dispatch middleware extension method UseEndpointDispatcherMiddleware.

Either way the UseEndpointRouteResolverMiddleware() endpoint resolver middleware will have access to the route mappings at request handling time to do the route matching.

Once the route is matched by UseEndpointRouteResolverMiddleware an Endpoint object will be constructed with the route parameters and set to the httpcontext so that the middleware in the pipeline that follow, can access the Endpoint object and use it if needed.

In version 3 preview 3 version of this pseudo code, the route mapping is passed to UseEndpointRouteResolverMiddleware and there does not exist a UseEndpointDispatcherMiddleware at the end of the pipeline. This is because in this version the ASP.NET framework itself implicitly dispatches the resolved endpoint at the end of the request pipeline.

So the pseudo code representing version 3 preview 3 has the form below:

//pseudo code representing v3 preview 3 endpoint routing API
public void Configure(IApplicationBuilder app
                     , IHostingEnvironment env)
{
    app.UseBeforeEndpointResolutionMiddleware()

    //This is the endpoint route resolver middleware
    app.UseEndpointRouteResolverMiddleware(routes =>
    {
        //The route mapping configuration is passed to the endpoint resolution middleware
        routes.MapControllers();
    })

    //This middleware can access the resolved endpoint object via HttpContext
    app.UseAfterEndpointResolutionMiddleware()

    // The resolved endpoint is implicitly dispatched here at the end of the pipeline
    // and so there is no explicit call to a UseEndpointDispatcherMiddleware
}

This API looks to be changing with the 3.0 release version, as the current source code shows that the UseEndpointDispatcherMiddleware is added back in and it is the middleware that takes the route mappings as a parameter as illustrated by the second version of the pseudo code above.

Endpoint routing in version 2.2

If you create a Web API project using version 2.2 of the .NET Core SDK you will see the following code in the Startup.Configure method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    app.UseHttpsRedirection();

    //By default endpoint routing is not added
    //the MVC middleware dispatches the controller action
    //and the MVC middleware configures the default route mapping
    app.UseMvc();
}

The MVC middleware is configured at the end of the middleware pipeline using the UseMvc() extension method. This method internally sets the default MVC route mapping configuration at startup configuration time and dispatches the controller action during request handling.

By default the out of the box template in v2.2 just configures the MVC dispatcher middleware. As such the MVC middleware also handles the route resolution based on the route map configuration and the incoming request data.

However we can add Endpoint Routing using some additional configuration as shown below:

using Microsoft.AspNetCore.Internal;

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    //added endpoint routing that will resolve the endpoint object
    app.UseEndpointRouting();

    //middleware below will have access to the Endpoint

    app.UseHttpsRedirection();

    //the MVC middleware dispatches the controller action
    //and the MVC middleware configures the default route mapping
    app.UseMvc();
}

Here we have added the namespace Microsoft.AspNetCore.Internal. Including it, enables an additional IApplicationBuilder extension method UseEndpointRouting that is the endpoint resolution middleware that resolves the route and adds the Endpoint object to the httpcontext.

You can check out the source code for UseEndpointRouting extension method in version 2.2 at:

https://github.com/aspnet/AspNetCore/blob/v2.2.4/src/Http/Routing/src/Internal/EndpointRoutingApplicationBuilderExtensions.cs

In version 2.2 the MVC middleware at the end of the pipeline acts as the endpoint dispatcher middleware. It will dispatch the resolved endpoint to the proper controller action.

The endpoint resolution middleware uses the route mappings configured by the MVC middleware.

Once we have enabled endpoint routing we can actually inspect the resolved endpoint object if we add our own custom middleware show below:

using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    app.UseEndpointRouting();

    app.UseHttpsRedirection();

    //our custom middlware
    app.Use((context, next) =>
    {
        var endpointFeature = context.Features[typeof(IEndpointFeature)] as IEndpointFeature;
        var endpoint = endpointFeature?.Endpoint;

        //note: endpoint will be null, if there was no resolved route
        if (endpoint != null)
        {
            var routePattern = (endpoint as RouteEndpoint)?.RoutePattern
                                                          ?.RawText;

            Console.WriteLine("Name: " + endpoint.DisplayName);
            Console.WriteLine($"Route Pattern: {routePattern}");
            Console.WriteLine("Metadata Types: " + string.Join(", ", endpoint.Metadata));
        }
        return next();
    });

    app.UseMvc();
}

As you can see we can inspect and print out the endpoint object that the endpoint routing resolution middleware UseEndpointRouting has resolved. The endpoint object will be null, if the resolver was not able to match the request to a mapped route. We needed to pull in two additional namespaces to access the endpoint routing features.

Endpoint routing in Version 3 preview 3

In version 3 preview 3, endpoint routing will become a full fledged citizen of ASP.NET Core and we will finally have separation between the MVC controller action dispatcher and the route resolution middleware.

Here is the endpoint startup configuration in version 3 preview 3.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    app.UseHttpsRedirection();

    app.UseRouting(routes =>
    {
        routes.MapControllers();
    });

    app.UseAuthorization();

    //No need to have a dispatcher middleware here.
    //The resolved endpoint is automatically dispatched to a controller action at the end
    //of the middleware pipeline
    //If an endpoint was not able to be resolved, a 404 not found is returned at the end
    //of the middleware pipeline
}

As you can see we have a app.UseRouting() method that configures the endpoint route resolution middleware. The method also takes a anonymous lambda function that configures the route mappings that the route resolver middleware will use to resolve the incoming request endpoint.

The routes.MapControllers() inside the mapping function configures the default MVC routes.

You will also notice that there is a app.UseAuthorization() after app.UseRouting() which configures the authorization middleware. This middleware will have access the httpcontext endpoint object set by the endpoint routing middleware.

Notice that we don’t have any MVC or endpoint dispatch middleware configured at the end of the method, after all other middleware configuration.

This is because the behavior of the version 3 preview 3 build is that the resolved endpoint will be implicitly dispatched to the controller action by the framework itself.

Similar to what we did for version 2.2 we can add the same custom middleware to inspect the resolved endpoint object.

using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    app.UseHttpsRedirection();

    app.UseRouting(routes =>
    {
        routes.MapControllers();
    });

    app.UseAuthorization();

    //our custom middleware
    app.Use((context, next) =>
    {
        var endpointFeature = context.Features[typeof(IEndpointFeature)] as IEndpointFeature;
        var endpoint = endpointFeature?.Endpoint;

        //note: endpoint will be null, if there was no
        //route match found for the request by the endpoint route resolver middleware
        if (endpoint != null)
        {
            var routePattern = (endpoint as RouteEndpoint)?.RoutePattern
                                                          ?.RawText;

            Console.WriteLine("Name: " + endpoint.DisplayName);
            Console.WriteLine($"Route Pattern: {routePattern}");
            Console.WriteLine("Metadata Types: " + string.Join(", ", endpoint.Metadata));
        }
        return next();
    });

    //the endpoint is dispatched by default at the end of the middleware pipeline
}

Endpoint routing in upcoming ASP.NET Core version 3.0 source code repository

As we approach the version 3.0 release of the framework, it looks like the team is trying to make endpoint routing more explicit by adding back in the call to endpoint dispatcher middleware configuration. They are also moving back the route mapping configuration option to the dispatcher middleware configuration method.

We can see how this is changed yet again by peeking at the current source code.

Here is a snippet from the source code for the version 3.0 sample application music store at:

https://github.com/aspnet/AspNetCore/blob/master/src/MusicStore/samples/MusicStore/Startup.cs

public void Configure(IApplicationBuilder app)
{
    // Configure Session.
    app.UseSession();

    // Add static files to the request pipeline
    app.UseStaticFiles();

    // Add the endpoint routing matcher middleware to the request pipeline
    app.UseRouting();

    // Add cookie-based authentication to the request pipeline
    app.UseAuthentication();

    // Add the authorization middleware to the request pipeline
    app.UseAuthorization();

    // Add endpoints to the request pipeline
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "areaRoute",
            pattern: "{area:exists}/{controller}/{action}",
            defaults: new { action = "Index" });

        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller}/{action}/{id?}",
            defaults: new { controller = "Home", action = "Index" });

        endpoints.MapControllerRoute(
            name: "api",
            pattern: "{controller}/{id?}");
    });
}

As you can see that we have something similar to my pseudo code implementation that I detailed above.

Particularly, we still have the app.UseRouting() middleware setup from the version 3 preview 3, but now we also have an explicit app.UseEndpoints() endpoint dispatch method that more aptly named for what it does.

The UseEndpoints is a new IApplicationBuilder extension method that provides the endpoint dispatch implementation.

You can check out the source code for the UseEndpoints and UseRouting methods here:

https://github.com/aspnet/AspNetCore/blob/master/src/Http/Routing/src/Builder/EndpointRoutingApplicationBuilderExtensions.cs

Also note that the route mapping configuration lambda have been moved from the UseRouting middleware to the new UseEndpoints middleware.

The UseRouting endpoint route resolver will still have access to the mappings to resolve the endpoint at request handling time. Even though they are passed to the UseEndpoints middleware during startup configuration.

Adding Endpoint routing middleware to the DI container

To use endpoint routing, we also need to add the middleware to the DI container in the Startup.ConfigureServices method.

ConfigureServices in Version 2.2

For version 2.2 of the framework we need to explicitly add the call to services.AddRouting() method shown below to add the endpoint routing feature to the DI container:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRouting()

    services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

ConfigureServices in Version 3 preview 3

For version 3 preview 3 build of the framework, endpoint routing already comes configured in the DI container under the covers in the AddMvc() extension method:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
            .AddNewtonsoftJson();
}

Setting up Endpoint Authorization using endpoint routing and route mappings

When working with the version 3 preview 3 release we can attach authorization metadata to an endpoint. We do this using the route mappings configuration fluent API RequireAuthorization method.

The endpoint routing resolver will access this metadata when processing a request and add it to the Endpoint object that it sets on the httpcontext.

Any middleware in the pipeline after the route resolution middleware can access this authorization data by accessing the resolved Endpoint object.

In particular the authorization middleware can use this data to make authorization decisions.

Currently the route mapping configuration parameters are passed into the endpoint route resolver middleware, but as previously mentioned, in the future releases, the route mapping configuration will be passed into the endpoint dispatcher middleware.

Either way the attached authorization metadata will be available for the endpoint resolver middleware to use.

Below is an example of the version 3 preview 3 Startup.Configure method where I have added a new /secret route to the endpoint resolver middleware route map configuration lambda parameter:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    app.UseHttpsRedirection();

    app.UseRouting(routes =>
    {
        routes.MapControllers();

        //Mapped route that gets attached authorization metadata using the RequireAuthorization extension method.
        //This metadata will be added to the resolved endpoint for this route by the endpoint resolver
        //The app.UseAuthorization() middleware later in the pipeline will get the resolved endpoint
        //for the /secret route and use the authorization metadata attached to the endpoint
        routes.MapGet("/secret", context =>
        {
            return context.Response.WriteAsync("secret");
        }).RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin" });
    });

    app.UseAuthentication();

    //the Authorization middleware check the resolved endpoint object
    //to see if it requires authorization. If it does as in the case of
    //the "/secret" route, then it will authorize the route, if it the user is in the admin role
    app.UseAuthorization();

    //the framework implicitly dispatches the endpoint at the end of the pipeline.
}

You can see that I am using the RequireAuthorization method to add an AuthorizeAttribute attribute to the /secret route. This route will then only be authorized to be dispatched for a user in the admin role, by the authorization middleware, that comes before the endpoint dispatch occurs.

As I showed for version 3.3 preview 3 that we can add middleware to inspect the resolved endpoint object in httpcontext so can we here to inspect the AuthorizeAttribute added to the endpoint metadata:

using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authorization;

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    app.UseHttpsRedirection();

    app.UseRouting(routes =>
    {
        routes.MapControllers();

        routes.MapGet("/secret", context =>
        {
            return context.Response.WriteAsync("secret");
        }).RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin" });
    });

    app.UseAuthentication();

    //our custom middleware
    app.Use((context, next) =>
    {
        var endpointFeature = context.Features[typeof(IEndpointFeature)] as IEndpointFeature;
        var endpoint = endpointFeature?.Endpoint;

        //note: endpoint will be null, if there was no
        //route match found for the request by the endpoint route resolver middleware
        if (endpoint != null)
        {
            var routePattern = (endpoint as RouteEndpoint)?.RoutePattern
                                                          ?.RawText;

            Console.WriteLine("Name: " + endpoint.DisplayName);
            Console.WriteLine($"Route Pattern: {routePattern}");
            Console.WriteLine("Metadata Types: " + string.Join(", ", endpoint.Metadata));
        }
        return next();
    });

    app.UseAuthorization();

    //the framework implicitly dispatches the endpoint here.
}

This time I have added the custom middleware before the Authorization middleware and pulled in two additional namespaces.

Navigating to the /secret route and inspecting the metadata, you can see that it contains the Microsoft.AspNetCore.Authorization.AuthorizeAttribute type in addition to the Microsoft.AspNetCore.Routing.HttpMethodMetadata type.

References used for this article

The following articles contain source material that I used as a reference for this article:

https://devblogs.microsoft.com/aspnet/aspnet-core-3-preview-2/

Update for version 3 preview 4

Around the time I published this article, ASP.NET Core 3.0 preview 4 was released. It adds the changes that I described in the latest source code as can be seen in the code snippet from Startup.cs file below when creating a new webapi project:

//code from Startup.cs file in a webapi project template

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
            .AddNewtonsoftJson();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
    else
        app.UseHsts();

    app.UseHttpsRedirection();

    //add endpoint resolution middlware
    app.UseRouting();

    app.UseAuthorization();

    //add endpoint dispatch middleware
    app.UseEndpoints(endpoints =>
    {
        //route map configuration
        endpoints.MapControllers();

        //route map I added to show Authorization setup
        endpoints.MapGet("/secret", context =>
        {
            return context.Response.WriteAsync("secret");
        }).RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin" }); 
    });
}

As you can see this version adds the explicit UseEndpoints middleware extension method at the end of the pipeline that adds the endpoint dispatch middleware. Also the route configuration parameter has been moved from the UseRouting method in preview 3 to the UseEndpoints in preview 4.

Conclusion

Endpoint routing allows ASP.NET Core applications to determine the endpoint that will be dispatched, early on in the middleware pipeline, so that later middleware can use that information to provide features not possible with the current pipeline configuration.

This makes the ASP.NET Core framework more flexible since it decouples the route matching and resolution functionality from the endpoint dispatching functionality, which until now was all bundled in with the MVC middleware.



European ASP.NET Core Hosting :: Getting Started with Entity Framework Core

clock January 21, 2020 08:13 by author Scott

This walkthrough demonstrates the minimum required to create a database using Entity Framework Core in an ASP.NET Core application, and to develop basic CRUD screens. The walkthrough assumes that you have .Net Core SDK installed and that you have a suitable development environment/text editor. Visual Studio Code will be used in this example.

Creating an ASP.NET Core application link

If you have a version of Visual Studio that supports .Net Core (2015 or greater), you can use the project templates to create a new .Net Core Web application. Alternatively, you can use a command line tool to create and build the project. In this example, you will use the command line tool from within Visual Studio Code.

The first step is to create a folder for the application in a suitable location. Name the folder EFCoreWebDemo. Once created, open the folder in Visual Studio Code. Having done that, press Ctrl + ' to open a Terminal window.

Next, use the terminal to type these commands

dotnet new mvc 
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package --version 1.1.0-msbuild3-final Microsoft.EntityFrameworkCore.Tools
dotnet restore     
dotnet run
         

The commands above

- scaffolds a starter ASP.NET Core application that uses the MVC framework

- adds the Entity FrameworkCore and EF Core tooling packages from Nuget to the project

- restores all packages

- builds and runs the application

You should get confirmation that the application is running on port 5000:

If you navigate to http://localhost:5000 in your preferred browser, you should see the standard Microsoft MVC application running:

To continue with the next steps, stop the application by pressing Ctrl + C.

Open the EFCoreDemo folder in Visual Studio Code.

Modify the .csproj file to include the following section:

<ItemGroup>
    <DotNetCliToolReference
        Include="Microsoft.EntityFrameworkCore.Tools.DotNet"
        Version="1.0.0-msbuild3-final" />
</ItemGroup>

This step is only necessary if the .csproj file wasn't automatically modified to add the entry when the Tools package was installed. See https://github.com/aspnet/EntityFramework/issues/7358.

Once you have made this amendment, you can test to see if ef commands are available to you by navigating to the project folder in a terminal/command window and typing the following command:

dotnet ef -h

This should result in the initial help for the EF tools being displayed:

Creating the Model

Add a folder named Model to the application.

Add a new file named EFCoreWebDemoContext.cs to the Model folder and add the following code to it:

using Microsoft.EntityFrameworkCore;

namespace EFCoreWebDemo
{
    public class EFCoreWebDemoContext : DbContext
    {
        public DbSet<Book> Books { get; set; }
        public DbSet<Author> Authors { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {         optionsBuilder.UseSqlServer(@"Server=.\;Database=EFCoreWebDemo;Trusted_Connection=True;MultipleActiveResultSets=true");
        }
    }
}

Note: The model, particularly the DbContext class, is declared inside a namespace. If you don't place your context class in a namespace, you may come up against this long running open bug when adding your migration.

Next, add a new file named Author.cs and add the following code to it:

using System.Collections.Generic;

namespace EFCoreWebDemo
{
    public class Author
    {
        public int AuthorId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public ICollection<Book> Books { get; set; } = new List<Book>();
    }
}

Finally, add a new file named Book.cs and add the following code to it:

namespace EFCoreWebDemo
{
    public class Book
    {
        public int BookId { get; set; }
        public string Title { get; set; }
        public int AuthorId { get; set; }
        public Author Author { get; set; }
    }
}

This code defines classes for two entities - Book and Author that participate in a fully defined one-to-many relationship. The code also includes a class named EFCoreDemoContext that inherits from DbContext. This class has two DbSet properties that represent the tables in the database (which is yet to be created). The EFCoreWebDemoContext class also includes a method named OnConfiguring where the connection string for a SQL Server database is defined. You should change this to suit your environment and database provider.

Before moving on to the migration, type dotnet build to ensure that the application builds correctly.

Adding A Migration

Migrations are used to keep the database schema in sync with the model. There is no database at the moment, so the first migration will create it and add tables for the entities represented by the DbSet properties on the EFCoreDemoContext that you added.

Visual Studio Code doesn't provide any support (at the time of writing) for creating and executing migrations. Therefore they will be managed using the command prompt. Having opened one (if it's not still open from having created and built the application), navigate to the project folder and enter the following command:

dotnet ef  migrations add CreateDatabase

A new folder named Migrations is added to the project. It contains the code for the migration and a model snapshot.

Enter the following command to execute the migration:

dotnet ef database update

The database is created but all of the string fields are unlimited in size (nvarchar(MAX) in SQL Server).

Modifying The Database With Migrations

In the next section, you will modify the model to set limits to the size of selected string properties, and then use migrations to push those changes to the database schema.

Add the following to the using directives at the top of Author.cs and Book.cs:

using System.ComponentModel.DataAnnotations;

Modify the Book and Author entities so that they look like this:

public class Book
{
    public int BookId { get; set; }
    [StringLength(255)]
    public string Title { get; set; }
    public int AuthorId { get; set; }
    public Author Author { get; set; }
}

public class Author
{
    public int AuthorId { get; set; }
    [StringLength(50)]
    public string FirstName { get; set; }
    [StringLength(75)]
    public string LastName { get; set; }
    public ICollection<Book> Books { get; set; } = new List<Book>();
}

In the Terminal, type the following command:

dotnet ef migrations add LimitStrings

followed by

dotnet ef database update

This will scaffold a migration that will alter the size of the Book's Title field and the Author's FirstName and LastName fields. You should also get a warning that the scaffolded migration could lead to data loss. In this case, there is no data to be lost so the warning can be ignored.

Once the migration has been applied, the database schema will be altered. Here's how the modified Author table should look:

Working With Data

In the next section, you will create a web page for adding new authors to the database and for displaying them. Add a new file named AuthorController.cs to the Controllers folder. Add the following code to the newly created file:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace EFCoreWebDemo.Controllers
{
    public class AuthorController : Controller
    {
        public async Task<IActionResult> Index()
        {
            using (var context = new EFCoreWebDemoContext())
            {
                var model = await context.Authors.AsNoTracking().ToListAsync();
                return View(model);
            }           
        } 

        [HttpGet]
        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Create([Bind("FirstName, LastName")] Author author)
        {
            using (var context = new EFCoreWebDemoContext())
            {
                context.Add(author);
                await context.SaveChangesAsync();
                return RedirectToAction("Index");
            }
        }
    }
}

The code in the Index method retrieves all authors from the database and passes them to the View. The AsNoTracking method is used to prevent the context from unnecessarily tracking the data because it is intended for read-only use. The DbContext is instantiated in a using block to ensure that it is disposed properly.

The Create method that takes an Author as a parameter is responsible for adding the new author to the database. It uses the approach whereby data is added directly to the DbContext, allowing the context to infer the type of data to be added to the database.

Finally, add a new folder to the Views folder and name it Author. Add new file to the new folder called Index.cshtml. Add the following code to it:

@model IEnumerable<Author>
@{
    ViewBag.Title = "Authors";
}
<h1>@ViewBag.Title</h1>
<ul>
@foreach (var author in Model)
{
    <li>@author.FirstName @author.LastName</li>
}
</ul>

<div>@Html.ActionLink("New", "create")

Then add a new file named Create.cshtml to the Author folder with the following code:

@model Author
@{
    ViewBag.Title = "New Author";
}

<h1>@ViewBag.Title</h1>

@using(Html.BeginForm()){
  <div class="form-group">
    @Html.LabelFor(model => model.FirstName)
    @Html.TextBoxFor(model => model.FirstName, new { @class="form-control"})
  </div>
  <div class="form-group">
    @Html.LabelFor(model => model.LastName)
    @Html.TextBoxFor(model => model.LastName, new { @class="form-control"})
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
}

Run the application by typing the following command:

dotnet run

Open a browser and navigate to http://localhost:5000/author/create. You should see a data entry form similar to this:

 

Enter an author's name and submit the form. You should get redirected to the index page where a list of any authors entered so far is displayed:

 

Adding Related Data

In the next section, you will add new books to the database which will be related to an existing author.

First, add a new file to the Controllers folder named BookController.cs. Add the following code to the new file:

using System.Threading.Tasks;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace EFCoreWebDemo.Controllers
{

    public class BookController : Controller
    {
        public async Task<IActionResult> Index()
        {
            using (var context = new EFCoreWebDemoContext())
            {
                var model = await context.Authors.Include(a => a.Books).AsNoTracking().ToListAsync();
                return View(model);
            }          
        } 

        [HttpGet]
        public async Task<IActionResult> Create()
        {
            using(var context = new EFCoreWebDemoContext())
            {
                var authors = await context.Authors.Select(a => new SelectListItem {
                    Value = a.AuthorId.ToString(),
                    Text = $"{a.FirstName} {a.LastName}"
                }).ToListAsync();
                ViewBag.Authors = authors;
            }
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Create([Bind("Title, AuthorId")] Book book)
        {
            using (var context = new EFCoreWebDemoContext())
            {
                context.Books.Add(book);
                await context.SaveChangesAsync();
                return RedirectToAction("Index");
            }
        }
    }
}

This time, the code in the Index method retrieves all authors and uses the Include method to eagerly load the related books from the database and passes them to the View. Again, the AsNoTracking method is used. The authors and their books only being used for display.

In the first Create method, each of the authors are retrieved from the database and projected into a new form - a SelectListItem. Non-entity types are not tracked by the context which is why the AsNoTracking method is not used in this case, despite the fact that the data is for read-only use.

The second Create method features an example of the entity being added to its DBSet, rather than the DbContext as was the case for the author.

Next, add a new folder to the Views folder named Book. Add a new file to the book folder named Index.cshtml and copy the following code into it:

@model IEnumerable<Author>
@{
                ViewBag.Title = “Authors and their books”;
}
<h1>@ViewBag.Title</h1>
@if(Model.Any()){
    <ul>
    @foreach(var author in Model){
        <li>@author.FirstName @author.LastName
            <ul>
            @foreach(var book in author.Books){
                <li>@book.Title</li>
            }
            </ul>
        </li>
    }
    </ul>
}
<div>@Html.ActionLink("New", "create")

Finally, add another file to the Views/Book folder named Create.cshtml and add the following code to it:

@model Book
@{
    ViewBag.Title = "New Book";
}

<h1>@ViewBag.Title</h1>

@using(Html.BeginForm()){
  <div class="form-group"
    @Html.LabelFor(model => model.AuthorId)
    @Html.DropDownListFor(model => model.AuthorId, (IEnumerable<SelectListItem>)ViewBag.Authors, string.Empty, new { @class="form-control"})
  </div>
  <div class="form-group">
    @Html.LabelFor(model => model.Title)
    @Html.TextBoxFor(model => model.Title, new { @class="form-control"})
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
}

Execute the dotnet run command to build and run the application. You might need to press Ctrl + C to stop the application first. Once it is running again, navigate to http://localhost:5000/book/create where you should see a data entry screen like this:

The AuthorId dropdown should be populated with the the authors that you have so far entered into the application. Select one and enter a book title and hit the submit button. You should then be redirected to the Index view which will display a list of all authors and their books.



European ASP.NET MVC Core Hosting :: Layout View ASP.NET Core MVC

clock November 28, 2019 07:58 by author Scott

Short tutorial only about Layout view in ASP.NET Core MVC. We will discuss about it. Let’s get started!

What is Layout?

The layouts are like the master pages in Webforms applications.  The common UI code, which can be used in many views can go into a common view called layout.

Why do we need Layout View in ASP.NET Core MVC?

Nowadays, almost all web applications have the following sections.

  • Website Header
  • Website Footer
  • Navigation Menus
  • Main Content Area

Please have a look at the following image which shows the above mentioned four areas on a website.

Instead of putting all the sections (i.e. the HTML) in each and every view pages, it is always better and advisable to put them in a layout view and then inherit that layout view in each and every view where you want that look and feel. With the help of layout views, now it is easier to maintain the consistent look and feel of your application. This is because if you at all need to do any changes then you need to do it only at one place i.e. in the layout view and the changes will be reflected immediately across all the views which are inherited from the layout view.

Layout View in ASP.NET Core MVC Application:

  1. Like the regular view in ASP.NET Core MVC, the layout view is also a file with a .cshtml extension
  2. If you are coming from ASP.NET Web Forms background, you can think the layout view as the master page in asp.net web forms application.
  3. As the layout views are not specific to any controller, so, we usually place the layout views in a subfolder called “Shared” within the “Views” folder.
  4. By default, in ASP.NET Core MVC Application, the layout view file is named _Layout.cshtml.
  5. The leading underscore in the file name indicates that these files are not intended to be served directly by the browser.
  6. In ASP.NET Core MVC, it is also possible to create multiple layout files for a single application. For example, you may have one layout file for the admin users and another layout file for non-admin users of your application.

How to Create a Layout View in ASP.NET Core MVC Application?

  1. In order to create a layout view in ASP.NET Core MVC, you need to follow the below steps.
  2. Right-click on the “Views” folder and then add a new folder with the name “Shared“.
  3. Next, Right-click on the “Shared” folder and then select the “Add” – “New Item” option from the context menu which will open the Add New Item window.
  4. From the “Add New Item” window search for Layout and then select “Razor Layout”, give a meaning full name (_Layout.cshtml) to your layout view and finally click on the “Add” button as shown below which should add _Layout.cshtml file within the Shared folder.

 

Note: In this article, I am going to show you how to create and use a layout file and in our upcoming articles, I will show you how to use website header, footer, and navigation menus.

Understanding the _Layout.cshtml file:

Let us have a look at the auto-generated HTML code in the _Layout.cshtml file. The following HTML is auto-generated in the _Layout.cshtml file.

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

As you can see in the above layout file, it contains the standard Html, head, title and body elements. As the above elements are present in the layout file, so you don’t have to repeat all the above elements in each and every view.

The View or Page-specific title is retrieved by using the @ViewBag.Title expression. For example, when “index.cshtml” view is rendered using this layout view, then the index.cshtml view will set the Title property on the ViewBag. This is then retrieved by the Layout view using the expression @ViewBag.Title and set as the value for the <title> tag.

The @RenderBody() specifies the location where the view or page-specific content is injected. For example, if “index.cshtml” view is rendered using this layout view, then index.cshtml view content is injected at the location.

Let us modify the _Layout.cshtml page as shown below to include the header, footer, left navigation menus and main content area section.

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <table border="1" style="width:800px; font-family:Arial">
        <tr>
            <td colspan="2" style="text-align:center">
                <h3>Website Header</h3>
            </td>
        </tr>
        <tr>
            <td style="width:200px">
                <h3>Left Navigation Menus</h3>
            </td>
            <td style="width:600px">
                @RenderBody()
            </td>
        </tr>
        <tr>
            <td colspan="2" style="text-align:center; font-size:x-small">
                <h3>Website Footer</h3>
            </td>
        </tr>
    </table>
</body>
</html>

Modifying the Startup class:

Please modify the Startup class as shown below where we configure the required services for MVC.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace FirstCoreMVCApplication
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseMvcWithDefaultRoute();
        }
    }
}

Modifying the Home Controller:

Please modify the Home Controller as shown below.

using Microsoft.AspNetCore.Mvc;
namespace FirstCoreMVCApplication.Controllers
{
    public class HomeController : Controller
    {
        public ViewResult Index()
        {
            return View();
        }       

        public ViewResult Details()
        {
            return View();
        }
    }
}

As you can see here we have created two action methods i.e. Index and View.

Using Layout view in ASP.NET Core MVC Application:

Now we are going to create the Index and Details views using the Layout view. In order to render a view using the layout view (_Layout.cshtml), you need to set the Layout property.

Index.cshtml:

Please modify the Index view as shown below to use the layout view.

@{
    ViewBag.Title = "Home Page";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Home Page</h1>

Details.cshtml:

Please modify the Details view as shown below to use the layout view.

@{
    ViewBag.Title = "Details Page";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Details Page</h1>

Now run the application and navigate to the Home/Index URL which should display the page as shown below.

If you don’t have a layout view for your website, then you need to repeat the required HTML for the above-mentioned sections in each and every view of your application. This is violating the DRY (Don’t Repeat Yourself) principle as we are repeating the same code in multiple views. As a result, it is very difficult to maintain the application. For example, if you have to remove or add a menu item from the list of navigation menus or even if you want to change the header or footer of your website then you need to do this in each and every view which is tedious, time-consuming as well as error-prone.



European ASP.NET MVC Hosting :: How to Integrate Your ASP.NET MVC with Paypal

clock March 5, 2019 08:27 by author Scott

PayPal is an online payment service that allows you to pay for purchases, receive payments, or to send and receive money. To receive these services, a person must submit various financial details to PayPal, such as credit card number, transmission can be done by mail. Thereafter, transactions are conducted without having to disclose financial details, an email address and a password is sufficient.

for more information about business please visit official Paypal Website for business or https://developer.paypal.com/webapps/developer/docs/integration/direct/log-in-with-paypal/detailed/

In this tutorial we propose to integrate the PAYPAL  e-commerce payment solution.

So, we are using Visual studio C# and ASP.NET MVC4 (for more information about ASP.NET MVC please take a look at  http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4

Ready ? Lets start our tutorial :

1. Open Visual studio 2012 or later and Create your Project

2.  Choose ASP.NET MVC4 Template Projet, Internet Application and Razor ViewEngine

 

3. Expand Model folder and Create a new Model named PayPalModel to hold PayPal payment parameters

Try it 

public class PayPalModel
{
public string cmd { get; set; }
public string business { get; set; }
public string no_shipping { get; set; }
public string @return { get; set; }
public string cancel_return { get; set; }
public string notify_url { get; set; }
public string currency_code { get; set; }
public string item_name { get; set; }
public string amount { get; set; }
public string actionURL { get; set; }

public PayPalModel(bool useSandbox)
{
this.cmd = “_xclick”;
this.business = ConfigurationManager.AppSettings[“business”];
this.cancel_return = ConfigurationManager.AppSettings[“cancel_return”];
this.@return = ConfigurationManager.AppSettings[“return”];
if (useSandbox)
{
this.actionURL = ConfigurationManager.AppSettings[“test_url”];
}
else
{
this.actionURL = ConfigurationManager.AppSettings[“Prod_url”];
}
// We can add parameters here, for example OrderId, CustomerId, etc….
this.notify_url = ConfigurationManager.AppSettings[“notify_url”];
// We can add parameters here, for example OrderId, CustomerId, etc….
this.currency_code = ConfigurationManager.AppSettings[“currency_code”];
}
}

4. Create a Paypal Controller

Try it :

public class PayPalController : Controller
{
public ActionResult RedirectFromPaypal()
{
return View();
}

public ActionResult CancelFromPaypal()
{
return View();
}

public ActionResult NotifyFromPaypal()
{
return View();
}

public ActionResult ValidateCommand(string product, string totalPrice)
{
return View();
}
}

5. Now Create a Partial View (ValidateCommand.csHtml)  to use our Model.  Do not forget that all fields must be of type hidden

try it :

@model PaypalMVC.Models.PayPalModel

<body>
<form id=”hiddenform” [email protected]>
@Html.HiddenFor(model => model.cmd)
@Html.HiddenFor(model => model.business)
@Html.HiddenFor(model => model.no_shipping)
@Html.HiddenFor(model => model.@return)
@Html.HiddenFor(model => model.cancel_return)
@Html.HiddenFor(model => model.notify_url)
@Html.HiddenFor(model => model.currency_code)
@Html.HiddenFor(model => model.item_name)
@Html.HiddenFor(model => model.amount)
</form>

<p style=”text-align: center”>
<h3>
Connecting to Paypal , please wait …

</h3>
</p>
</body>
@Scripts.Render(“~/bundles/jquery”)

<script type=”text/javascript” language=”javascript”>
$(this.document).ready(function () {
var form = $(“form”);
form.submit();
});
</script>

6. Now finish our ValidateCommand action of PayPalController

try it :

public ActionResult ValidateCommand(string product, string totalPrice)
{
bool useSandbox = Convert.ToBoolean(ConfigurationManager.AppSettings[“IsSandbox”]);
var paypal = new PayPalModel(useSandbox);

paypal.item_name = product;
paypal.amount = totalPrice;
return View(paypal);
}

7. Next finish our partialView by adding a jquery code to auto submit our form. The necessary scripts are  Jquery-{version}.js and    Jquery-{version}.min.js. Here we are used  @Scripts.Render(“~/bundles/jquery”)  to include all Jquery scripts.  A more better practice will be to export all javascript functions to external file but the submit function must be called just after displaying hidden field of our form

8. The next step is to create our checkOut form that dispays product name , Quantity, price and Total :

So expand View folder , expand Home folder and open index.csHtml file. Replace its contents by the following

try it : 

@{
ViewBag.Title = “Home Page”;
}
@using (Html.BeginForm(“ValidateCommand”, “PayPal”))
{
<div>
<table >
<tr>
<td>
product Name:
</td>
<td>
<input type=”text” name=”product” value=”Visual Studio 2013″ readonly />
</td>
</tr>
<tr>
<td>
Total Price:
</td>
<td>
$<input type=”text” name=”totalPrice” value=”14800″ readonly />
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type=”submit” name=”btnConfirm” value=”Check Out with Paypal” />
</td>
</tr>
</table>
</div>
}

9. we are at the end. Our final step is to update the web.config file with the appropriate settings

10. Let’s test and run the application

 

11. Confirm payment by clicking on button Check Out With PayPal, then you will be redirected to the payment page 

We have this page error because, we have not yet an valid account.

Now it time to create a test account by following this link https://developer.paypal.com/webapps/developer/docs/classic/lifecycle/ug_sandbox/#accounts

12. Open Web.config file and update business value with your test account 

 

13. So run again your application. Confirm or Cancel , etc…

Hope this tutorial helps you. 

 



European ASP.NET MVC Hosting :: Basic Routing in ASP.NET MVC

clock January 30, 2019 10:22 by author Scott

When getting started with ASP.NET MVC and/or the ASP.NET Web API, it can be overwhelming trying to figure out how it all works. These frameworks offer powerful features, and abstract away a good deal of pain associated with handling, routing, and responding to HTTP requests within an application. This is a great thing for seasoned developers who understand what it is the framework is doing “for” you (and how to modify that behavior, if desired). It also makes it easier for new or less-experienced folk to set up a basic site or API and watch it “just work.”

On the other hand, the abstraction can make it challenging for those new to the MVC world to understand just what is going on, and where the critical functionality they want to modify “lives.”

One of the fundamental concepts to understand when using ASP.NET MVC and/or the ASP.NET Web API is routing, which essentially defines how your application will process and respond to incoming HTTP requests.

Routing Makes it All Work

Traditional web communication architecture maps a URL (Uniform Resource Locator) to a file within the file system. For example, the following:

http://mydomain.com/mybooks/favorites.html

would tend to map to a file named favorites.html, in the directory ~/mybooks/favorites, located in the root directory for the site mydomain.com. In response to an incoming HTTP request for this resource, the contents of the file are either returned (as in the example above, as HTML) or perhaps code associated with a file is executed (if, for example, the file were a .aspx file).

Within the MVC framework, as well as the Web API*, URLs are instead mapped to specific methods which execute in response to the incoming request, generally returning either a View (MVC) or some sort of structured data (Web API) corresponding to the the requested resource. In other words, instead of pointing to actual physical resources within a file system, MVC and Web API routes instead point to an abstraction which represents the resource requested, in both cases a method which will return the requested item.

This de-coupling of the URL from the physical file system allows us to construct cleaner, more friendly URLs which are more beneficial to the user, search-engine-friendly, and (in theory) more persistent, meaning URLs associated with specific content are less likely to change, and break incoming links. 

How Routing Works in ASP.NET MVC

In MVC, the convention is to map URLs to a particular action (a method) on a particular controller. The action then executes, and (usually, but not always) returns an instance of ActionResult. The ActionResult class handles Framework logic such as rendering to HTML or JSON, and writing to the HTTP response that will be returned to the user’s browser.

Once again, I defer to the authors of ASP.NET MVC 4 (who happen to also be members of the ASP.NET team):

The most basic version of this convention would be a URL as follows:

http://mydomain/controllername/methodname

In an MVC project, this is achieved by registering route templates which establish how incoming URLs will be mapped to specific controllers and actions. A typical MVC project defines a Global.asx file, which contains a single method – Application_Start. Within this method, calls are made to various configuration methods to set up the application’s working state. One of these calls is to the RegisterRoutes method of the RouteConfig class found in the App_Start folder of the project.

Global.asx File and the RouteConfig File in a Typical MVC Project:

If we examine the Global.asx file, we find the following code:

The Default ASP.NET MVC Global.asx File:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

For our purposes, we are interested only in the call to RouteConfig.RegisterRoutes. As we can see, the call passes the the Routes collection of the Global RouteTable as a parameter to the RegisterRoutes method, which then populates the routes collection with pre-defined route templates for the application. The default MVC project template comes with a single pre-configured route:

The Default MVC RouteConfig Class:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new
            {
                controller = "Home",
                action = "Index",
                id = UrlParameter.Optional
            }
        );
    }
}

Note that any MVC application must have at least one route definition in order to function. In the above, a route template named “Default” is added to the routes collection. The items in curly braces enclose Route Parameters, and are represented by the parameter name as a placeholder between the curly braces. Route Segments are separated by forward slashes (much like a standard URL). Notice how the implied relative URL our route specifies matches the MVC convention:

~/{controller}/{action}

Route parameters can be named just about anything, however ASP.NET recognizes a few special route parameter names, in particular {controller} and {action}, and treats them differently than other route parameters.

Controller Matching

When the routing framework encounters a route parameter named {controller}, it appends the suffix “Controller” to the value of the parameter, and then scans the project for a class by that name which also implements the System.Web.Mvc.IController interface. Note that the search for a controller with a matching name is case-insensitive.

Action Matching

Once the framework has selected the proper controller, it attempts to locate an action on the controller with a name matching the {action} parameter value. The search for a matching action name is case-insensitive. If more than one action matches by name (as with multiple overloaded methods on the same controller), the framework will select the method for which the most URL parameters match method arguments by name.

Action Parameter Matching

Additional URL Parameters other than {controller} and {action} are available to be passed as arguments to the selected Action method. The framework will evaluate the input arguments of the available actions, and match them by name (case-insensitively) to the URL parameters other than {action} and {controller}. With certain restrictions, the framework will select that action with the greatest number of matching parameters.

Some things to consider:

  • The MVC framework will first match method arguments by name to URL parameters. Then, it will attempt to match any query string parameters included in the URL by name. If the request is a POST, then the framework will attempt to match the contents of the POST body.
  • Method arguments are evaluated for a match by name only. The framework does not consider the type required by the method argument. For example, a URL parameter named {id} with a value of “John” will be considered a match for a method which accepts an int argument named id.
  • Action methods can be decorated with attributes which restrict the type of HTTP request they will respond to. Such attributes indicate the applicable HTTP verb to which the action will respond.

As an example of limiting the HTTP actions which a method may respond, consider the following:

Overloaded Action Method with HttpPost Attribute:

public ActionResult Edit(int id)
{
    return View();
}
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    try
    {
        // TODO: Add update logic here
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}
 

In the above, we find two methods named Edit. The first accepts an int named id as an argument, and the second accepts an int named id and a FormCollection (a complex type). The purpose of this overloaded method is so that a browser can:

  • Request a view with which to edit a record of some sort and then,
  • Submit the modified record values back to the site for storage.

The first Edit method, which requires only an int id argument will be called using HTTP GET, and return a view with the current representation of the data to be edited. Once the user has updated values in the view and submits the form data, an HTTP POST request is issued. The overloaded Edit method, decorated with the [HttpPost] attribute, is executed, and the modified data is persisted or otherwise processed. 

The MVC Default Route Template – Routing Walk-Thru

The route mapping assumes that the URL template specified is relative to the domain root for your site. In other words, since the entire application is hosted at http://yourdomain.com it is not necessary to include this domain root as part of the route template.

In the case of the default MVC mapping from our RouteConfig class above, the route contains the two special parameters, {controller} and {action}. In processing incoming requests, the framework appends “Controller” to the value provided for the {controller} parameter, and then searches the project for a controller class of that name. Once the proper controller has been identified, MVC next looks for a method name corresponding to the value of the {action} parameter, and then attempts to match any additional parameters with input arguments accepted by that method.

For example, if our application receives a request with the following URL:

http://mybookstore.com/books/details/25

the routing will match the default template. The string “Controller” will be appended to the “books” segment, and the runtime will set about searching the project for a class named BooksController. If the controller is located, MVC will then examine the controller for a public method named Details. If a Details method is found, MVC will attempt to find an overload which accepts a single argument named id, and then calls that method, passing in the final URL segment (“25” in this case) as an argument.

The following controller example would provide a suitable match for our incoming request:

A Simple Books Controller:

public class BooksController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    public ActionResult Details(int id)
    {
        return View();
    }
}

The incoming request would result in a call to the Details method, passing in the integer 25 as the proper id argument. The method would return the appropriate view (how MVC does this is another convention for another post – let’s stay focused on request routing for now).

Route Parameter Defaults

Notice in the RegisterRoutes method, the registration of the “Default” route also appears to assign some default values to the controller and action, parameters. These values will be used for any of these parameters if they are missing from the incoming request URL. Additionally, the id parameter is designated as optional. For example, consider the following URL:

http://mybookstore.com/books/

In this case, we have specified the Books controller, but have not specified a value for the action or id. However, this route still matches our route definition, since MVC will provide the default value specified for the action parameter (in this case, index). Since the id parameter has been made optional in our route template, MVC will again search for a controller named BooksController, but in this case, examine the controller for a method named Index which does not require an argument. Again, a match is found, and the Index method is called, returning an appropriate view (most likely a list of all the books in the database).

The MVC default route mapping also specifies a default controller to use when no controller parameter is specified; namely, the “Home” controller. In other words, incoming requests to our domain root:

http://mybookstore.com/

will also match the default project controller. In this case, the runtime will attempt to locate a controller named HomeController, then locate the Index method of that controller. Since no id parameter was provided, the Index method will be called, returning the appropriate view ( most likely, the Homepage of our site).

What Next?

As we have seen above, MVC examines an incoming URL and attempts to map each URL segment to a controller and action according to the route templates set up in the RouteConfig.MapRoutesmethod. Once a proper controller and action have been identified, any additional URL segments (for example, the optional {id} segment in our example above) are evaluated against the action method signature to determine the best parameter match for the action.

But what happens when we need to do more than just send an ID in as an argument for the desired action method? Or, what if we have one or more overloaded methods by which we wish to perform more complex queries against our data?

While we can always include query parameters as part of our URL (and in fact we will no doubt have to resort to this at various points in our application design), we can customize and extend the default routing, and exert a little more control over how how and what our application will accept in an HTTP request by customizing our routes.

While the default /controller/action/id route baked into the MVC project template is a useful start and will handle many common controller cases, it is safe to say the MVC team did not expect developers to limit their applications to this minimally-flexible, single standard. Indeed, the ASP.NET routing framework (and the corresponding routing framework used by Web API) are very flexible, and within certain limits, highly customizable.



European ASP.NET MVC Hosting :: Basic Routing in ASP.NET MVC

clock January 30, 2019 10:22 by author Scott

When getting started with ASP.NET MVC and/or the ASP.NET Web API, it can be overwhelming trying to figure out how it all works. These frameworks offer powerful features, and abstract away a good deal of pain associated with handling, routing, and responding to HTTP requests within an application. This is a great thing for seasoned developers who understand what it is the framework is doing “for” you (and how to modify that behavior, if desired). It also makes it easier for new or less-experienced folk to set up a basic site or API and watch it “just work.”

On the other hand, the abstraction can make it challenging for those new to the MVC world to understand just what is going on, and where the critical functionality they want to modify “lives.”

One of the fundamental concepts to understand when using ASP.NET MVC and/or the ASP.NET Web API is routing, which essentially defines how your application will process and respond to incoming HTTP requests.

Routing Makes it All Work

Traditional web communication architecture maps a URL (Uniform Resource Locator) to a file within the file system. For example, the following:

http://mydomain.com/mybooks/favorites.html

would tend to map to a file named favorites.html, in the directory ~/mybooks/favorites, located in the root directory for the site mydomain.com. In response to an incoming HTTP request for this resource, the contents of the file are either returned (as in the example above, as HTML) or perhaps code associated with a file is executed (if, for example, the file were a .aspx file).

Within the MVC framework, as well as the Web API*, URLs are instead mapped to specific methods which execute in response to the incoming request, generally returning either a View (MVC) or some sort of structured data (Web API) corresponding to the the requested resource. In other words, instead of pointing to actual physical resources within a file system, MVC and Web API routes instead point to an abstraction which represents the resource requested, in both cases a method which will return the requested item.

This de-coupling of the URL from the physical file system allows us to construct cleaner, more friendly URLs which are more beneficial to the user, search-engine-friendly, and (in theory) more persistent, meaning URLs associated with specific content are less likely to change, and break incoming links. 

How Routing Works in ASP.NET MVC

In MVC, the convention is to map URLs to a particular action (a method) on a particular controller. The action then executes, and (usually, but not always) returns an instance of ActionResult. The ActionResult class handles Framework logic such as rendering to HTML or JSON, and writing to the HTTP response that will be returned to the user’s browser.

Once again, I defer to the authors of ASP.NET MVC 4 (who happen to also be members of the ASP.NET team):

The most basic version of this convention would be a URL as follows:

http://mydomain/controllername/methodname

In an MVC project, this is achieved by registering route templates which establish how incoming URLs will be mapped to specific controllers and actions. A typical MVC project defines a Global.asx file, which contains a single method – Application_Start. Within this method, calls are made to various configuration methods to set up the application’s working state. One of these calls is to the RegisterRoutes method of the RouteConfig class found in the App_Start folder of the project.

Global.asx File and the RouteConfig File in a Typical MVC Project:

If we examine the Global.asx file, we find the following code:

The Default ASP.NET MVC Global.asx File:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

For our purposes, we are interested only in the call to RouteConfig.RegisterRoutes. As we can see, the call passes the the Routes collection of the Global RouteTable as a parameter to the RegisterRoutes method, which then populates the routes collection with pre-defined route templates for the application. The default MVC project template comes with a single pre-configured route:

The Default MVC RouteConfig Class:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new
            {
                controller = "Home",
                action = "Index",
                id = UrlParameter.Optional
            }
        );
    }
}

Note that any MVC application must have at least one route definition in order to function. In the above, a route template named “Default” is added to the routes collection. The items in curly braces enclose Route Parameters, and are represented by the parameter name as a placeholder between the curly braces. Route Segments are separated by forward slashes (much like a standard URL). Notice how the implied relative URL our route specifies matches the MVC convention:

~/{controller}/{action}

Route parameters can be named just about anything, however ASP.NET recognizes a few special route parameter names, in particular {controller} and {action}, and treats them differently than other route parameters.

Controller Matching

When the routing framework encounters a route parameter named {controller}, it appends the suffix “Controller” to the value of the parameter, and then scans the project for a class by that name which also implements the System.Web.Mvc.IController interface. Note that the search for a controller with a matching name is case-insensitive.

Action Matching

Once the framework has selected the proper controller, it attempts to locate an action on the controller with a name matching the {action} parameter value. The search for a matching action name is case-insensitive. If more than one action matches by name (as with multiple overloaded methods on the same controller), the framework will select the method for which the most URL parameters match method arguments by name.

Action Parameter Matching

Additional URL Parameters other than {controller} and {action} are available to be passed as arguments to the selected Action method. The framework will evaluate the input arguments of the available actions, and match them by name (case-insensitively) to the URL parameters other than {action} and {controller}. With certain restrictions, the framework will select that action with the greatest number of matching parameters.

Some things to consider:

  • The MVC framework will first match method arguments by name to URL parameters. Then, it will attempt to match any query string parameters included in the URL by name. If the request is a POST, then the framework will attempt to match the contents of the POST body.
  • Method arguments are evaluated for a match by name only. The framework does not consider the type required by the method argument. For example, a URL parameter named {id} with a value of “John” will be considered a match for a method which accepts an int argument named id.
  • Action methods can be decorated with attributes which restrict the type of HTTP request they will respond to. Such attributes indicate the applicable HTTP verb to which the action will respond.

As an example of limiting the HTTP actions which a method may respond, consider the following:

Overloaded Action Method with HttpPost Attribute:

public ActionResult Edit(int id)
{
    return View();
}
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    try
    {
        // TODO: Add update logic here
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}
 

In the above, we find two methods named Edit. The first accepts an int named id as an argument, and the second accepts an int named id and a FormCollection (a complex type). The purpose of this overloaded method is so that a browser can:

  • Request a view with which to edit a record of some sort and then,
  • Submit the modified record values back to the site for storage.

The first Edit method, which requires only an int id argument will be called using HTTP GET, and return a view with the current representation of the data to be edited. Once the user has updated values in the view and submits the form data, an HTTP POST request is issued. The overloaded Edit method, decorated with the [HttpPost] attribute, is executed, and the modified data is persisted or otherwise processed. 

The MVC Default Route Template – Routing Walk-Thru

The route mapping assumes that the URL template specified is relative to the domain root for your site. In other words, since the entire application is hosted at http://yourdomain.com it is not necessary to include this domain root as part of the route template.

In the case of the default MVC mapping from our RouteConfig class above, the route contains the two special parameters, {controller} and {action}. In processing incoming requests, the framework appends “Controller” to the value provided for the {controller} parameter, and then searches the project for a controller class of that name. Once the proper controller has been identified, MVC next looks for a method name corresponding to the value of the {action} parameter, and then attempts to match any additional parameters with input arguments accepted by that method.

For example, if our application receives a request with the following URL:

http://mybookstore.com/books/details/25

the routing will match the default template. The string “Controller” will be appended to the “books” segment, and the runtime will set about searching the project for a class named BooksController. If the controller is located, MVC will then examine the controller for a public method named Details. If a Details method is found, MVC will attempt to find an overload which accepts a single argument named id, and then calls that method, passing in the final URL segment (“25” in this case) as an argument.

The following controller example would provide a suitable match for our incoming request:

A Simple Books Controller:

public class BooksController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    public ActionResult Details(int id)
    {
        return View();
    }
}

The incoming request would result in a call to the Details method, passing in the integer 25 as the proper id argument. The method would return the appropriate view (how MVC does this is another convention for another post – let’s stay focused on request routing for now).

Route Parameter Defaults

Notice in the RegisterRoutes method, the registration of the “Default” route also appears to assign some default values to the controller and action, parameters. These values will be used for any of these parameters if they are missing from the incoming request URL. Additionally, the id parameter is designated as optional. For example, consider the following URL:

http://mybookstore.com/books/

In this case, we have specified the Books controller, but have not specified a value for the action or id. However, this route still matches our route definition, since MVC will provide the default value specified for the action parameter (in this case, index). Since the id parameter has been made optional in our route template, MVC will again search for a controller named BooksController, but in this case, examine the controller for a method named Index which does not require an argument. Again, a match is found, and the Index method is called, returning an appropriate view (most likely a list of all the books in the database).

The MVC default route mapping also specifies a default controller to use when no controller parameter is specified; namely, the “Home” controller. In other words, incoming requests to our domain root:

http://mybookstore.com/

will also match the default project controller. In this case, the runtime will attempt to locate a controller named HomeController, then locate the Index method of that controller. Since no id parameter was provided, the Index method will be called, returning the appropriate view ( most likely, the Homepage of our site).

What Next?

As we have seen above, MVC examines an incoming URL and attempts to map each URL segment to a controller and action according to the route templates set up in the RouteConfig.MapRoutesmethod. Once a proper controller and action have been identified, any additional URL segments (for example, the optional {id} segment in our example above) are evaluated against the action method signature to determine the best parameter match for the action.

But what happens when we need to do more than just send an ID in as an argument for the desired action method? Or, what if we have one or more overloaded methods by which we wish to perform more complex queries against our data?

While we can always include query parameters as part of our URL (and in fact we will no doubt have to resort to this at various points in our application design), we can customize and extend the default routing, and exert a little more control over how how and what our application will accept in an HTTP request by customizing our routes.

While the default /controller/action/id route baked into the MVC project template is a useful start and will handle many common controller cases, it is safe to say the MVC team did not expect developers to limit their applications to this minimally-flexible, single standard. Indeed, the ASP.NET routing framework (and the corresponding routing framework used by Web API) are very flexible, and within certain limits, highly customizable.



European ASP.NET Core Hosting - HostForLIFE.eu :: How to Use Sessions and HttpContext in ASP.NET 5 and MVC6

clock February 24, 2017 06:56 by author Scott

If you’ve started work on a new ASP.NET 5, MVC 6 application you may have noticed that Sessions don’t quite work the way they did before. Here’s how to get up and running the new way.

Remove DNX Core Reference

Many simple ASP.NET components aren’t supported by the DNX Core Runtime. These usually surface with weird build errors. It’s much easier to just remove it from your project.json file. If it’s already not there, beautiful you don’t need to do anything

"frameworks": {
    "dnx451": { },
    "dnxcore50": { } // <-- Remove this line
},

Add Session NuGet Package

Add the Microsoft.AspNet.Session NuGet package to your project.

VERSION WARNING: If you’re using ASP.NET 5 before RTM, make sure the beta version is the same across your whole project. Just look at your references and make sure they all end with beta8 (or whichever version you’re using).

Update startup.cs

Now that we have the Session nuget package installed, we can add sessions to the OWIN pipline.

Open up startup.cs and add the AddSession() and AddCaching() lines to the ConfigureServices(IServiceCollection services)

// Add MVC services to the services container.
services.AddMvc();
services.AddCaching(); // Adds a default in-memory implementation of IDistributedCache
services.AddSession();

Next, we’ll tell OWIN to use a Memory Cache to store the session data. Add the UseSession() call below.

// IMPORTANT: This session call MUST go before UseMvc()
app.UseSession();

// Add MVC to the request pipeline.
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action}/{id?}",
        defaults: new { controller = "Home", action = "Index" });

    // Uncomment the following line to add a route for porting Web API 2 controllers.
    // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
});

Where’s the Session variable gone?

Relax it’s still there, just not where you think it is. You can now find the session object by using HttpContext.Session. HttpContext is just the current HttpContext exposed to you by the Controller class.

If you’re not in a controller, you can still access the HttpContext by injecting IHttpContextAccessor.

Let’s go ahead and add sessions to our Home Controller:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        HttpContext.Session.SetString("Test", "Ben Rules!");
        return View();
    }

    public IActionResult About()
    {
        ViewBag.Message = HttpContext.Session.GetString("Test");

        return View();
    }
}

You’ll see the Index() and About() methods making use of the Session object. It’s pretty easy here, just use one of the Set() methods to store your data and one of the Get() methods to retrieve it.

Just for fun, let’s inject the context into a random class:

public class SomeOtherClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private ISession _session => _httpContextAccessor.HttpContext.Session;

    public SomeOtherClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void TestSet()
    {
        _session.SetString("Test", "Ben Rules!");
    }

    public void TestGet()
    {
        var message = _session.GetString("Test");
    }
}

Let’s break this down.

Firstly I’m setting up a private variable to hold the HttpContextAccessor. This is the way you get the HttpContext now.

Next I’m adding a convenience variable as a shortcut directly to the session. Notice the =>? That means we’re using an expression body, aka a shortcut to writing a one liner method that returns something.

Moving to the contructor you can see that I’m injecting the IHttpContextAccessor and assigning it to my private variable. If you’re not sure about this whole dependency injection thing, don’t worry, it’s not hard to get the hang of (especially constructor injection like I’m using here) and it will improve your code by forcing you to write it in a modular way.

But wait a minute, how do I store a complex object?

How do I store a complex object?

I’ve got you covered here too. Here’s a quick JSON storage extension to let you store complex objects nice and simple.

public static class SessionExtensions
{
    public static void SetObjectAsJson(this ISession session, string key, object value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T GetObjectFromJson<T>(this ISession session, string key)
    {
        var value = session.GetString(key);

        return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
    }
}

Now you can store your complex objects like so:

var myComplexObject = new MyClass();
HttpContext.Session.SetObjectAsJson("Test", myComplexObject);

and retrieve them just as easily:

var myComplexObject = HttpContext.Session.GetObjectFromJson<MyClass>("Test");

Use a Redis or SQL Server Cache instead

Instead of using services.AddCaching() which implements the default in-memory cache, you can use either of the following.

Firstly, install either one of these nuget packages:

  • Microsoft.Framework.Caching.SqlServer
  • Microsoft.Framework.Caching.Redis

Secondly, add the appropriate code snippet below:

// Microsoft SQL Server implementation of IDistributedCache.
// Note that this would require setting up the session state database.
services.AddSqlServerCache(o =>
{
                o.ConnectionString = "Server=.;Database=ASPNET5SessionState;Trusted_Connection=True;";
                o.SchemaName = "dbo";
                o.TableName = "Sessions";
});

 

// Redis implementation of IDistributedCache.
// This will override any previously registered IDistributedCache service.
services.AddSingleton<IDistributedCache, RedisCache>();

 



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Angular 2 Contact Form Component for ASP.NET MVC 6

clock February 16, 2017 07:20 by author Scott

In this post, I will show you simple tutorial about how to create a simple contact form using Angular 2 and ASP.NET MVC 6. Ok, let’s get started.

The Component

Contact.cshtml

We’ll start off with a simple contact form. I’m asking the user for his name, e-mail address, a subject and of course the message itself. 
You’ll notice that I’m also using a bit of Bootstrap css classes. You however can of course use anything you want to style the contact form.

<div>
    <form #f="ngForm" (ngSubmit)="onSubmit(contact)">
        <div>
            <div class="form-group required">
                <label for="name">Name</label>
                <input type="text" [(ngModel)]="contact.Name" name="contact.Name" required="Please enter your name" class="form-control text-input" id="name" placeholder="Name"/>
            </div>
            <div class="form-group required">
                <label for="email">E-mail</label>
                <input type="email" [(ngModel)]="contact.Email" name="contact.Email" required="Please enter your e-mail address" class="form-control text-input" id="email" placeholder="E-mail"/>
            </div>
        </div>
        <div>
            <div class="form-group required">
                <label for="subject">Subject</label>
                <input type="text" [(ngModel)]="contact.Subject" name="contact.Subject" required="A subject is needed" class="form-control text-input" id="subject" placeholder="Subject"/>
            </div>
        </div>
        <div>
            <div class="form-group required">
                <label for="message">Message</label>
                <textarea type="text" [(ngModel)]="contact.Message" name="contact.Message" required="A message is needed" class="form-control" id="message" placeholder="Message..."></textarea>
            </div>
        </div>
        <div>
            <div>
                <button type="submit" class="btn btn-success">Send</button>
            </div>
        </div>
    </form>
</div>

Contact.ts

This the most important part of this post. I’ve written the code in Typescript. 
Due to an issue I couldn’t seem to resolve between MVC6 and Angular 2 I was forced to the URLSearchParams from Angular to send my data to the server. I hope to update this one day so I only have to send the complete object to the server.

import {Component} from '@angular/core';
import {Http, Headers, URLSearchParams} from '@angular/http';

@Component({
    selector: 'contact',
    templateUrl: '/angular/contact'
})

export class ContactFormComponent {
    http = undefined;
    contact = { Name: undefined, Subject: undefined, Email: undefined, Message: undefined };
    loading = true;

    constructor(http: Http) {
        this.http = http;
        this.loading = false;
    }

    onSubmit() {
        this.loading = true;
        let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
        var params = new URLSearchParams();
        params.set('Name', this.contact.Name);
        params.set('Subject', this.contact.Subject);
        params.set('Message', this.contact.Message);
        params.set('Email', this.contact.Email);
        this.http.post('/contact/send', params.toString(), { headers: headers }).subscribe(this.messageSend());
    }

    messageSend() {
        this.contact = { Name: undefined, Subject: undefined, Email: undefined, Message: undefined };
        this.loading = false;
    }
}

This was the biggest part, now what’s left is the connection on the server itself.

Start.cs

First we’ll setup the routes. This is very easy. I’ve set up a rout to go to the contact form itself and one for sending the information to the server.

public class Startup
{
                public void ConfigureServices(IServiceCollection services)
                {
                                //I'm using MVC... So I'm adding MVC.
                                services.AddMvc();
                }

                public void Configure(IApplicationBuilder app)
                {
                                //I have some static files, like images and css in my wwwroot folder. So I need to add these.
                                app.UseStaticFiles();
                                app.UseMvc(m =>
                                {
                                                //Route to open the page with the form.
                                                m.MapRoute("contact", "contact", new { controller = "Contact", action = "Contact" });
                                                //Route to post the data
                                                m.MapRoute("contact-send", "contact/send", new { controller = "Contact", action = "SendContact" });
                                });
                }

                // Entry point for the application.
                public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}

ContactVm.cs

This is going to be the ViewModel. I use this to map the JSON request to a nice and easy model we can use on our controller.

public class ContactVm
{
                [Required]
                [DataType(DataType.Text)]
                public string Name { get; set; }
                [Required]
                [DataType(DataType.EmailAddress)]
                public string Email { get; set; }
                [Required]
                [DataType(DataType.Text)]
                public string Subject { get; set; }
                [Required]
                [DataType(DataType.MultilineText)]
                public string Message { get; set; }
}

ContactController.cs

The last part is our controller itself where the data is being received on the server. Nothing special here, I’m just using the above viewmodel as a parameter.

public class ContactController : Controller
{
                public ContactController() { }

                public IActionResult Contact()
                {
                                return View();
                }             

                [HttpPost]
                public void SendContact(ContactVm contact)
                {
                                //Do something with the contact form...
                }
}

By using the above code you’ll be able create a contact form in Angular 2 and make it interact with and MVC 6 server-side.
Keep in mind the both frameworks are still in development and can contain errors.



European ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Use AngularJS with MVC 6 Web API

clock February 10, 2017 08:46 by author Scott

This post will walk you through the step-by-step procedure on building a simple ASP.NET 5 application using AngularJS with Web API.

Before we dig further let’s talk about a quick overview of AngularJS and Web API in MVC 6.

Introducing AngularJS

AngularJS is a client-side MVC framework written in JavaScript. It runs in a web browser and greatly helps us (developers) to write modern, single-page, AJAX-style web applications. It is a general purpose framework, but it shines when used to write CRUD (Create Read Update Delete) type web applications.

Introducing Web API

ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework. In ASP.NET 5, Web API is now part of MVC 6. Read more here

Creating an ASP.NET 5 Project

To start, fire up Visual Studio 2015 and create a new ASP.NET 5 project by selecting File > New Project. In the dialog, under Templates > Visual C#, select ASP.NET Web Application as shown in the figure below: 

Name your project to whatever you like and then click OK. For this example I named the project as “AngularJS101”. Now after that you should be able to see the “New ASP.NET Project” dialog:

Now select ASP.NET 5 Preview Empty template from the dialog above. Then click OK to let Visual Studio generate the necessary files and templates needed for you. You should be able to see something like below:

Adding the Scripts folder

The next thing to do is to create a new folder called “Scripts”. This folder will contain all the JavaScript files needed in our application:

Getting the Required Packages

ASP.NET 5 now supports three main package managers: NuGet, NPM and Bower.

Package Manager

A package manager enables you to easily gather all resources that you need for building an application. In other words you can make use of package manager to automatically download all the resources and their dependencies instead of manually downloading project dependencies such as jQuery, Bootstrap and AngularJS in the web.

NuGet

NuGet manages .NET packages such as Entity Framework, ASP.NET MVC and so on. You typically specify the NuGet packages that your application requires within project.json file.

NPM

NPM is one of the newly supported package manager in ASP.NET 5. This package manager was originally created for managing packages for the open-source NodeJS framework. The package.json is the file that manages your project’s NPM packages.

Bower

Bower is another supported package manager in ASP.NET 5. It was created by Twitter that is designed to support front-end development. You can use Bower to manage client-side resources such as jQuery, AngularJS and Bootstrap.

For this example we need to use NPM to install the resources we need in our application such as Grunt and the Grunt plugins. To do this just right click in your Project (in this case AngularJS101) and select Add > New Item. In the dialog select NPM configuration file as shown in the figure below:

Click Add to generate the file for you. Now open package.json file and modify it by adding the following dependencies:

{
    "version": "1.0.0",
    "name": "AngularJS101",
    "private": true,
    "devDependencies": {
        "grunt": "0.4.5",
        "grunt-contrib-uglify": "0.9.1",
        "grunt-contrib-watch": "0.6.1"
    }
}

Notice that you get Intellisense support while you edit the file. A matching list of NPM package names and versions shows as you type.

In package.json file, from the code above, we have added three (3) dependencies named grunt, grunt-contrib-uglify and grunt-contrib-watch NPM packages that are required in our application.

Now save the package.json file and you should be able to see a new folder under Dependencies named NPM as shown in the following:

Right click on the NPM folder and select Restore Packages to download all the packages required. Note that this may take a bit to finish the download so just be patient and wait ;). After that the grunt, grunt-contrib-uglify and grunt-contrib-watch NPM packages should now be installed as shown in the following:

Configuring Grunt

Grunt is an open-source tool that enables you to build client-side resources for your project. For example, you can use Grunt to compile your LESS or Saas files into CSS. Adding to that, Grunt can also be used to minify CSS and JavaScript files.

In this example, we will use Grunt to combine and minify JavaScript files. We will configure Grunt so that it will take all the JavaScript files from the Scripts folder that we created earlier, combine and minify the files, and finally save the results to a file named app.js within the wwwroot folder.

Now right click on your project and select Add > New Item. Select Grunt Configuration file from the dialog as shown in the figure below:

Then click Add to generate the file and then modify the code within the Gruntfile.js file so it will look like this:

module.exports = function (grunt) { 
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.initConfig({
        uglify: {
            my_target: {
                files: { 'wwwroot/app.js': ['Scripts/app.js', 'Scripts/**/*.js'] }
            }
        },

        watch: {
            scripts: {
                files: ['Scripts/**/*.js'],
                tasks: ['uglify']
            }
        }
    });

    grunt.registerTask('default', ['uglify', 'watch']);
};

The code above contains three sections. The first one is used to load each of the Grunt plugins that we need from the NPM packages that we configured earlier. The initConfig() is responsible for configuring the plugins. The Uglify plugin is configured so that it combines and minifies all the files from the Scripts folder and generate the result in a file named app.js within wwwroot folder. The last section contains the definitions for your tasks. In this case we define a single ‘default’ task that runs ‘uglify’ and then watches for changes in our JavaScript file.

Now save the file and let’s run the Grunt file using Visual Studio Task Runner Explorer. To do this, go to View > Other Windows > Task Runner Explorer in Visual Studio main menu. In the Task Runner Explorer make sure to hit the refresh button to load the tasks for our application. You should see something like this:

Now right click on the default task and select Run. You should be able to see the following output:

Configuring ASP.NET MVC

There are two main files that we need to modify to enable MVC in our ASP.NET 5 application.

First, we need to modify the project.json file to in include MVC 6 under dependencies:

    "webroot": "wwwroot",
    "version": "1.0.0-*",
    "dependencies": {
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta3",
        "Microsoft.AspNet.Mvc": "6.0.0-beta3"
    },
    "frameworks": {
        "aspnet50": { },
        "aspnetcore50": { }
    },

Make sure to save the file to restore the packages required. The project.json file is used by the NuGet package manager to determine the packages required in your application. In this case we’ve added Microsoft.AspNet.Mvc.

Now the last thing is to modify the Startup.cs file to add the MVC framework in the application pipeline. Your Startup.cs file should now look like this:

using System; 
using Microsoft.AspNet.Builder; 
using Microsoft.AspNet.Http; 
using Microsoft.Framework.DependencyInjection;

namespace AngularJS101 
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services){
            services.AddMvc();
        }

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

The ConfigureServices() method is used to register MVC with the ASP.NET 5 built-in Dependency Injection Framework (DI). The Configure() method is used to register MVC with OWIN.

Adding Models

The next step is to create a model that we can use to pass data from the server to the browser/client. Now create a folder named “Models” under the root of your project. Within the “Models” folder, create a class named “DOTAHero” and add the following code below:

using System;

namespace AngularJS101.Models 
{
    public class DOTAHero
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
    }
}

Create another class called “HeroManager” and add the following code below:

using System.Collections.Generic; 
using System.Linq;

namespace AngularJS101.Models 
{
    public class HeroManager
    {
        readonly List<DOTAHero> _heroes = new List<DOTAHero>() {
            new DOTAHero { ID = 1, Name = "Bristleback", Type="Strength"},
            new DOTAHero { ID = 2, Name ="Abbadon", Type="Strength"},
            new DOTAHero { ID = 3, Name ="Spectre", Type="Agility"},
            new DOTAHero { ID = 4, Name ="Juggernaut", Type="Agility"},
            new DOTAHero { ID = 5, Name ="Lion", Type="Intelligence"},
            new DOTAHero { ID = 6, Name ="Zues", Type="Intelligence"},
            new DOTAHero { ID = 7, Name ="Trent", Type="Strength"},
        };
        public IEnumerable<DOTAHero> GetAll { get { return _heroes; } }

        public List<DOTAHero> GetHeroesByType(string type) {
            return _heroes.Where(o => o.Type.ToLower().Equals(type.ToLower())).ToList();
        }

 public DOTAHero GetHeroByID(int Id) {
            return _heroes.Find(o => o.ID == Id);
        }
    }
}

The HeroManager class contains a readonly property that contains a list of heroes. For simplicity, the data is obviously static. In real scenario you may need to get the data in a storage medium such as database or any files that stores your data. It also contains a GetAll property that returns all the heroes and a GetHeroesByType() method that returns a list of heroes based on the hero type, and finally a GetHeroByID() method that returns a hero based on their ID.

Adding Web API Controller

For this particular example, we will be using Web API for passing data to the browser/client.

Unlike previous versions of ASP.NET, MVC and Web API controllers used the same controller base class. Since Web API is now part of MVC 6 then we can start creating Web API controllers because we already pulled the required NuGet packages for MVC 6 and configured MVC 6 in startup.cs.

Now add an “API” folder under the root of the project:

Then add a Web API controller by right-clicking the API folder and selecting Add > New Item. Select Web API Controller Class and name the controller as “HeroesController” as shown in the figure below:

Click Add to generate the file for you. Now modify your HeroesController class so it will look like this:

using System.Collections.Generic; 
using Microsoft.AspNet.Mvc; 
using AngularJS101.Models;

namespace AngularJS101.API.Controllers 
{
    [Route("api/[controller]")]
    public class HeroesController : Controller
    {
        // GET: api/values
        [HttpGet]
        public IEnumerable<DOTAHero> Get()
        {
            HeroManager HM = new HeroManager();
            return HM.GetAll;
        }

        // GET api/values/7
        [HttpGet("{id}")]
        public DOTAHero Get(int id)
        {
            HeroManager HM = new HeroManager();
            return HM.GetHeroByID(id);
        }

    }
}

At this point we will only be focusing on GET methods to retrieve data. The first GET method returns all the heroes available by calling the GetAll property found in HeroManager class. The second GET method returns a specific hero data based on the ID.

You can test whether the actions are working by running your application in the browser and appending the /api/heroes in the URL. Here are the outputs for both GET actions:

Route: /api/heroes

Route: /api/heroes/7

Creating an AngularJS Application

Visual Studio 2015 includes templates for creating AngularJS modules, controllers, directives and factories. For this example we will be displaying the list of heroes using an AngularJS template.

Adding an AngularJS Module

To get started lets create an AngularJS module by right-clicking on the Scripts folder and selecting Add > New Item. Select AngularJS Module as shown in the figure below.

Click Add to generate the file and copy the following code for our AngularJS module:

(function () {
    'use strict';

    angular.module('heroesApp', [
        'heroesService'      
    ]);
})();

The code above defines a new AngularJS module named “heroesApp”. The heroesApp has a dependency on another AngularJS module named “heroesService” which we will create later in the next step.

Adding an AngularJS Controller

The next thing to do is to create a client-side AngularJS Controller. Create a new folder called “Controllers” under the Script folder as in the following:

 

Click Add and copy the following code below within your heroesController.js file:

(function () {
    'use strict';

    angular
        .module('heroesApp')
        .controller('heroesController', heroesController);

    heroesController.$inject = ['$scope','Heroes'];

    function heroesController($scope, Heroes) {
        $scope.Heroes = Heroes.query();
    }
})();

The code above depends on the Heroes service that supplies the list of heroes. The Heroes service is passed to the controller using dependency injection (DI). The $inject() method call enables DI to work. The Heroes service is passed as the second parameter to the heroesController() function.

Adding the Heroes Service

We will use an AngularJS Heroes service to interact with our data via Web API. Now add a new folder called “Services” within the Script folder. Right click on the Services folder and select Add > New Item. From the dialog select AngularJS Factory and name it as “heroesService.js” as in the following:

Now click Add and then replace the generated default code with the following:

(function () {
    'use strict';

    var heroesService = angular.module('heroesService', ['ngResource']);
    heroesService.factory('Heroes', ['$resource',
        function ($resource) {
            return $resource('/api/heroes', {}, {
                query: { method: 'GET', params: {}, isArray: true}
            });
        }
    ]);
})();

The code above basically returns a list of heroes from the Web API action. The $resource object performs an AJAX request using a RESTful pattern. The heroesService is associated with the /api/heroes route on the server. This means that when you perform a query against the service from your client-side code, the Web API HeroesController is invoked to return a list of heroes.

Adding an AngularJS Template

Let’s add an AngularJS template for displaying the list of heroes. To do this we will need an HTML page to render in the browser. In the wwwroot folder add a new HTML page and name it as “index” for simplicity. Your application structure should now look like this:

The wwwroot folder is a special folder in your application. The purpose is that the wwwroor folder should contain all contents of your website such as HTML files and images needed for your website.

You should not place any of your source code within the wwwroot folder. Instead source codes such as MVC controllers’ source, model classes and unminified JavaScript and LESS files should be placed outside of the wwwroot folder.

Now replace the content of index.html with the following:

<!DOCTYPE html>  
<html ng-app="heroesApp"> 
<head> 
    <meta charset="utf-8" />
    <title>DOTA 2 Heroes</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-resource.js"></script>
    <script src="app.js"></script>
</head> 
<body ng-cloak> 
    <div ng-controller="heroesController">
        <h1>DOTA Heroes</h1>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Type</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="hero in Heroes">
                    <td>{{hero.ID}}</td>
                    <td>{{hero.Name}}</td>
                    <td>{{hero.Type}}</td>
                </tr>
            </tbody>
        </table>
    </div>
</body> 
</html> 

There are several things to point out from the markup above: 
The html element is embedded with the ng-app directive. This directive associates the heroesApp with the HTML file.

In the script section, you will notice that I use Google CDN for referencing AngularJS and related libraries. Besides being lazy, it’s my intent to use CDN for referencing standard libraries such as jQuery, AngularJS and Bootstrap to boost application performance. If you don’t want to use CDN then you can always install AngularJS packages using Bower.

The body element is embedded with the ng-cloak directive. This directive hides an AngularJS template until the data has been loaded in the page. 
The div element within the body block is embedded with the ng-controller directive. This directive associates the heroesController and renders the data within the div element.

Finally, the ng-repeat directive is added to the tr element of the table. This will create row for each data that retrieved from the server.

Output

Here’s the output below when running the page and navigating to index.html:

That’s it! It is more fun to play DOTA!

 



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.


Tag cloud

Sign in