All About ASP.NET and ASP.NET Core 2 Hosting BLOG

Tutorial and Articles about ASP.NET and the latest ASP.NET Core

ASP.NET Core Hosting - ASPHostPortal :: How to Integrate Stripe Payment with ASP.NET Core

clock July 15, 2019 11:53 by author Jervis

Stripe is a service for doing online payments. It's easy to get started with it because they take care of both the frontend and the backend. The frontend scripting is available for many different frameworks like React, Android, IOS and of course JavaScript and with different levels of customization. The backend is also available in almost any backend framework one could wish for, like .NET. We will discuss the different options for a JavaScript frontend, the .NET package for Stripe as the title suggests, and lastly, the use of Webhooks.

Choosing a frontend option

The frontend uses tokens to represent the card’s information. It does so by preventing the default submission of the form and creating a token of the card’s information by contacting the Stripe servers. This ensures you never need to handle personal card information on your server. It is recommended to use a SSL certificate on the payment site to ensure no one can intercept the information that the client script sends.

Stripe.js is the most basic and lightweight option and the one most customizable. It supplies a clean multipart input where the user can fill in their card nr., expiration date and CVC nr. The input instantly detects the card type and validates of the card nr. and expiration date. You can read more about the integration of Stripe.js in Stripe's guide.

 

 

Secure payments

 

From the 4th of September 2019 new security standards will apply for online payments in the EU. So, if you are targeting an European or global customer segment, you should have this in mind. The EU council PSD2 continuously work on making online payment safer for the users. This requires payments to be done using an extra step of security. You have probably already seen such methods and the one most popularly used by different banks is 3D Secure. This is already an integrated part of the Checkout solution, but is not a supported feature in Stripe.js without performing some extra steps. To enable this for Stripe.js you will need to use a PaymentIntent.

Registering at Stripe.com

Before getting started with coding you need an account at Stripe. You get this by going to their register page and filling out the form. After you are done with this you can access the Stripe dashboard. A nice feature that we will need in this experimental test phase is the View test data, which you can enable/disable directly in the menu. This option switches between real and test payments, API keys and so on. To see and create API keys go to Developers>API keys. You have both publishable and secret keys, but you should never use the secret key on the frontend. These keys differ depending on if you are in testing mode or not, so make sure to switch to live keys when you publish your site.

 

 

The main menu in the Stripe dashboard

Creating a payment

We chose to use MVC in our example and have made a Controller for payments and associated views. We chose to use the Checkout for our frontend, because it has the simplest setup.

@{
    ViewData["Title"] = "Payment";
}

<div>
    <form action="/Payment/Processing" method="POST">
        <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
                data-key="pk_test_YourPublishAbleKey"
                data-amount="@ViewBag.PaymentAmount"
                data-name="[My Company Name]"
                data-description="10 rubberducks for 1$ each"
                data-image=
https://stripe.com/img/documentation/checkout/marketplace.png
                data-locale="en"
                data-zip-code="true"
                data-label="Pay 10$">
        </script>
    </form>
</div>

The elements in the form are made by the referenced JavaScript, so this is all you need for the frontend for now. You can change the form to your liking by using the data attributes. An example could be to fill out the amount dynamically using a ViewModel or ViewBag as shown. Other options such as specifying the currency (US Dollars is the default) can be added as well and you can read more about this in Stripe's guide for Checkout. On submit, the form posts the inputs to the action specified, which include the strings stripeToken and stripeEmail by default. Stripe.js also creates the input named stripeToken on submit, so the frontend can easily be switched to that implementation.

To get started on the backend we first need to add the package NuGet Stripe.net to our project. We then need to define the API key that we will use and a good convention is to set this in the Configure-method in Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //Your other configuration
    StripeConfiguration.SetApiKey(Configuration["Stripe:TestSecretKey"]);
}

We refence our API key using User Secrets, but you could use App Settings or an inline string instead, if that fits your style better.

We can now make the controller for our Payment Views and the post:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using Stripe;

namespace StripeTest.Controllers
{
    public class PaymentController : Controller
    {
        private int amount = 100;
        public IActionResult Index()
        {
            ViewBag.PaymentAmount = amount;
            return View();
        }

        [HttpPost]
        public IActionResult Processing(string stripeToken, string stripeEmail)
        {
            Dictionary<string, string> Metadata = new Dictionary<string, string>();
            Metadata.Add("Product", "RubberDuck");
            Metadata.Add("Quantity", "10");
            var options = new ChargeCreateOptions
            {
                Amount = amount,
                Currency = "USD",
                Description = "Buying 10 rubber ducks",
                SourceId = stripeToken,
                ReceiptEmail = stripeEmail,
                Metadata = Metadata
            };
            var service = new ChargeService();
            Charge charge = service.Create(options);
            return View();
        }
    }
}

We take the two parameters stripeToken and stripeEmail in our action, but could add more, like information about the billing address, if you enable that in the frontend (if you have more inputs than this, a better approach would be to use a model for the form, but for now this should be fine).

We would like to add some metadata to the charge which we will use later. This is done using a Dictionary.

We then create a ChargeCreateOption object which contains the information about the Charge, where we pass in stripeToken and the Metadata Dictionary. We then create a ChargeService and use the ChargeCreateOption to make the charge. The Status of the Charge is at first pending and will change to either succeeded or failed when the charge has been processed by Stripe.

Respond to the payment

But what now? How do we know the Status of the charge? There are two different ways of getting the Status of the charge.

We can Retrieve the charge. This is done using a ChargeService again and using the action .Get(id) which takes the id of the Charge as a parameter, which we would have to save when we create it. The status could still be pending when we make the request, so we would have to run the request multiple times in intervals to check.

We can use Webhooks. In the Dashboard, we can specify an endpoint that will be called when a Charge changes status and use this to take actions on our server when we need to and not make unnecessary requests.

We decide to use Webhooks. We first need to make the Webhook on our page. We simply add another action to our Controller:

private readonly string WebhookSecret = "whsec_OurSigningSecret";

//Previous actions

[HttpPost]
public IActionResult ChargeChange()
{
    var json = new StreamReader(HttpContext.Request.Body).ReadToEnd();

    try
    {
        var stripeEvent = EventUtility.ConstructEvent(json,
            Request.Headers["Stripe-Signature"], WebhookSecret, throwOnApiVersionMismatch: true);
        Charge charge = (Charge)stripeEvent.Data.Object;
        switch (charge.Status)
        {
            case "succeeded":
                //This is an example of what to do after a charge is successful
                charge.Metadata.TryGetValue("Product", out string Product);
                charge.Metadata.TryGetValue("Quantity", out string Quantity);
                Database.ReduceStock(Product, Quantity);
                break;
            case "failed":
                //Code to execute on a failed charge
                break;
        }
    }
    catch (Exception e)
    {
        e.Ship(HttpContext);
        return BadRequest();
    }
    return Ok();
}

We have made the Action ChargeChange which starts by reading the body that was passed with the post. We then try to construct the event and cast it to the Charge type.

Now we just need to have Stripe call our Webhook, which is done in the dashboard in the menu Developers>Webhooks and selecting Add endpoint. We then enter the path of our webhook, which would be something like:

https://mysite.com/Payment/ChargeChange/

We can also choose to have it only access our webhook for certain types of changes, like only when a it changes to charge.succeeded or charge.failed. After this you can go into the Endpoint in the list and see our Webhook Secret.

 

This is a basic start for how to work with Stripe. They have many more features we didn't get to cover, including the new PaymentIntent and the setup of Subscriptions. It's easy to imagine many more technologies that Stripe could be used together with, like SignalR for real-time response on a status update of a Charge. 



ASP.NET Core Hosting :: How to Implement Custom Error Pages in ASP.NET MVC Core

clock July 11, 2019 10:01 by author Jervis

We just recently saw people ask this questions on forums, so we decide to write short brief tutorial to make custom error pages in ASP.NET MVC Core.

So, let’s start how to implement custom error pages 404s and exceptions on this blog.

Custom error pages

Anyone know what is custom error pages? It is great looking view when something goes wrong in a production environment.

In development you would use:

app.UseDeveloperExceptionPage();

Now when an exception occurs, you will see a view that describes what went wrong and where.

But it should not be used in production as it could lead to security problems. Users might also consider your site less stable, and never visit again.

So we want to show them something that says something like:

Oops! Something went wrong. We are very sorry, please try again in a moment. If the error persists...

In case of a 404 status code, by default ASP.NET Core just returns a white page.

Instead we would like to show something like:

Hey that thing you tried to access does not exist. Please check the URL is correct.

Exception handler middleware

Let's start by handling exceptions properly.

In our application pipeline configuration, we will add the exception handler middleware:

if(!env.IsDevelopment())
{
    app.UseExceptionHandler("/error/500");
}

So what does this middleware do?

Well, put simply it:

  1. Calls the next middleware with a try-catch block
  2. If an exception is caught, the next middleware is called again with the request path set to what you gave as an argument

This re-execution means the original URL is preserved in the browser.

The controller and action that is implemented looks like this:

[Route("error")]
public class ErrorController : Controller
{
    private readonly TelemetryClient _telemetryClient;

    public ErrorController(TelemetryClient telemetryClient)
    {
        _telemetryClient = telemetryClient;
    }

    [Route("500")]
    public IActionResult AppError()
    {
        var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        _telemetryClient.TrackException(exceptionHandlerPathFeature.Error);
        _telemetryClient.TrackEvent("Error.ServerError", new Dictionary<string, string>
        {
            ["originalPath"] = exceptionHandlerPathFeature.Path,
            ["error"] = exceptionHandlerPathFeature.Error.Message
        });
        return View();
    }
}

I took a look at the source code of the exception handler middleware, and found that it sets this IExceptionHandlerPathFeature on the context before re-executing the request.

Here we access it to get the relative URL the user tried to access and the exception that occurred. We use Application Insights to track the exception.

The view is pretty simple:

@{
    ViewBag.Title = "Error occurred";
}

<h1>We have a problem</h1>

<p>Sorry, an error occurred while executing your request.</p>

Now when an exception is thrown:

  1. The exception is logged in Application Insights
  2. User gets a nice-looking view instead of a stack trace
  3. The original URL is preserved in the browser so the user can try to refresh
  4. The response comes back with a 500 status code so it is tracked as a failed request in Application Insights

Handling 404s

We also want to handle 404 status codes gracefully.

In this blog, it could happen because the URL did not map to a controller action. Or it might have, but we could not find something in the database.

404s are handled with a small middleware that is placed before the MVC middleware:

app.Use(async (ctx, next) =>
{
    await next();

    if(ctx.Response.StatusCode == 404 && !ctx.Response.HasStarted)
    {
        //Re-execute the request so the user gets the error page
        string originalPath = ctx.Request.Path.Value;
        ctx.Items["originalPath"] = originalPath;
        ctx.Request.Path = "/error/404";
        await next();
    }
});

Re-executing a request is not hard as you can see. We just call await next(); again.

Here we grab the original URL and put it in the HttpContext.Items collection.

This is the action that then handles the error in the ErrorController introduced earlier:

[Route("404")]
public IActionResult PageNotFound()
{
    string originalPath = "unknown";
    if (HttpContext.Items.ContainsKey("originalPath"))
    {
        originalPath = HttpContext.Items["originalPath"] as string;
    }
    _telemetryClient.TrackEvent("Error.PageNotFound", new Dictionary<string, string>
    {
        ["originalPath"] = originalPath
    });
    return View();
}

We track the event with a custom event in Application Insights, and include the original URL in the properties.

The view is quite simple again:

@{
    ViewBag.Title = "404";
}

<h1>404 - Page not found</h1>

<p>Oops, better check that URL.</p>

If you open the browser DevTools, you can again see we get the right status code: 404.

And the original URL is preserved in the browser.

Happy Coding!



ASP.NET Core 2.2 Hosting :: Feature Flags with ASP.NET Core 2.2

clock June 25, 2019 08:09 by author Jervis

Feature flags can be useful for changing the runtime behavior of an application with minimal impact. Having a UI to toggle the feature flags on and off is extra helpful, too!

That said, we built a library to enable this in a strongly typed fashion! Here’s what the UI looks like:

Installation

Install the RimDev.AspNetCore.FeatureFlags NuGet package.

> dotnet add package RimDev.AspNetCore.FeatureFlags

Or

PM> Install-Package RimDev.AspNetCore.FeatureFlags

Usage

You’ll need to wire up Startup.cs as follows:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using RimDev.AspNetCore.FeatureFlags;

namespace MyApplication
{
    public class Startup
    {
        private static readonly FeatureFlagOptions options = new FeatureFlagOptions()
            .UseCachedSqlFeatureProvider(@"CONNECTION_STRING_HERE");

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddFeatureFlags(options);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseFeatureFlags(options);

            // IMPORTANT: Controlling access of the UI / API of this library is the responsibility of the user.
            // Apply authentication / authorization around the `UseFeatureFlagsUI` method as needed,
            // as this method wires up the various endpoints.
            app.UseFeatureFlagsUI(options);
        }
    }
}

Next, create feature flags like this in the ASP.NET Core assembly:

using RimDev.AspNetCore.FeatureFlags;

namespace MyApplication
{
    public class MyFeature : Feature
    {
        // Optional, displays on UI:
        public override string Description { get; } = "My feature description.";
    }
}

NoteFeatureFlagAssemblies to scan can also be configured in FeatureFlagOptions if you’d like to scan assemblies other than Assembly.GetEntryAssembly().

Now you can dependency inject any of your feature flags using the standard ASP.NET Core IoC!

public class MyController : Controller
{
    private readonly MyFeature myFeature;

    public MyController(MyFeature myFeature)
    {
        this.myFeature = myFeature;
    }

    // Use myFeature instance here, using myFeature.Value for the on/off toggle value.
}

UI

The UI wired up by UseFeatureFlagsUI is available by default at /_features. The UI and API endpoints can be modified in FeatureFlagOptions if you’d like, too.

In closing

We hope this helps you control your applications in production, enabling rapid development while controlling access to new functionality in a controlled manner – decoupled from your deployments. Enjoy!



ASP.NET Core Hosting :: How to Create CRUD App Using Blazor and ASP.NET Core

clock April 12, 2019 07:43 by author Jervis

Blazor is an experimental .NET web framework using C#/Razor and HTML that runs in the browser via WebAssembly. It simplifies the process of creating single page application (SPA) and at the same time also brings the power of .NET on the table. It runs in the browser on a real .NET runtime (Mono) implemented in WebAssembly that executes normal .NET assemblies. In this post, we’ll see how to set up blazor and create a CRUD app using blazor and ASP.NET Core.

Creating a Blazor App

To create a blazor app, open Visual Studio 2017 “Preview” version, hit Ctrl+Shift+N and select the ASP.NET Core Web Application (.NET Core) project type from the templates. When you click Ok, you will get the following prompt,

If you don’t see these blazor templates, make sure .NET Core and ASP.NET Core 2.0 are selected at the top. As you can see, there are 2 blazor templates. The standalone “Blazor” template will create a static blazor app and “Blazor (ASP.NET Core Hosted)” will create an ASP.NET Core hosted blazor app. Choose “Blazor (ASP.NET Core Hosted)” to create the blazor app. Now, our first Blazor app will be created. In the solution explorer, you will find 3 projects created.

  • <Project Name>.Client: Standard blazor application.
  • <Project Name>.Server: It’s an ASP.NET Core Web API project.
  • <Project Name>.Shared: It’s a .NET standard class library project used for holding the shared resources.

You should run the app to make sure that there are no errors. Press Ctrl-F5 to run the app without the debugger. Running with the debugger (F5) is not supported at this time. Next thing is to extend this app to create a CRUD app.

Create the CRUD App

Before we move on, take a look at the following image to get an idea of what we are building.

As you can see, we are building a ToDo List app supporting all the CRUD operations and a listing of the ToDo items. We’ll use Entity Framework Core in-memory provider to store the ToDo list. So let’s begin.

First, create a ToDoList class in the Shared project with the following code. It’s a simple class with only two members.

public class ToDoList
{
    public int ID { get; set; }

    public string Item { get; set; }
}

Next, create EF DBContext to interact with the database. To do that, create a new folder named “Data” in the Server project. Add a new class file named ToDoListContext with the following code.

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

    public DbSet<ToDoList> ToDoLists { get; set; }
}

We’ll need to configure InMemory db provider. To do that, Open Startup.cs class and navigate to the ConfigureServices method to configure it (Line no. 4).

public void ConfigureServices(IServiceCollection services)
{
    // Use Entity Framework in-memory provider for this sample
    services.AddDbContext<ToDoListContext>(options => options.UseInMemoryDatabase("ToDoList"));

    services.AddMvc().AddJsonOptions(options =>
    {
        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
    });

    services.AddResponseCompression(options =>
    {
        options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
        {
            MediaTypeNames.Application.Octet,
            WasmMediaTypeNames.Application.Wasm,
        });
    });
}

Next, we’ll need an API controller for all CRUD operations. To do that, create a new controller named ToDoListController inside the Controller folder in the Server project with the following code.

[Produces("application/json")]
[Route("api/ToDo")]
public class ToDoListController : Controller
{
    private readonly ToDoListContext _context;

    public ToDoListController(ToDoListContext context)
    {
        _context = context;
    }

    // GET: api/ToDo
    [HttpGet]
    public IEnumerable<ToDoList> GetToDo()
    {
        return _context.ToDoLists;
    }

    // POST: api/ToDo
    [HttpPost]
    public async Task<IActionResult> PostToDo([FromBody] ToDoList todo)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        _context.ToDoLists.Add(todo);
        await _context.SaveChangesAsync();
        return CreatedAtAction("GetToDo", new { id = todo.ID }, todo);
    }

    // PUT: api/ToDo/5
    [HttpPut("{id}")]
    public async Task<IActionResult> PutToDo([FromRoute] int id, [FromBody] ToDoList todo)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        if (id != todo.ID)
            return BadRequest();

        _context.Entry(todo).State = EntityState.Modified;
        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!ToDoExists(id))
                return NotFound();
            else
                throw;
        }
        return NoContent();
    }

    // DELETE: api/ToDo/5
    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteToDo([FromRoute] int id)
    {
        var ToDo = await _context.ToDoLists.SingleOrDefaultAsync(m => m.ID == id);
        if (ToDo == null)
            return NotFound();

        _context.ToDoLists.Remove(ToDo);
        await _context.SaveChangesAsync();
        return Ok(ToDo);
    }

    private bool ToDoExists(int id)
    {
        return _context.ToDoLists.Any(e => e.ID == id);
    }
}

Here, the controller has API for all CRUD operations with proper validations. Quite familiar piece of code, isn’t it?

Blazor App Code

Next, we need to add the ToDo component to the Client App. The default app is already having Home, Counter and Fetch Data component. To add ToDo component, right-click on Pages folder and select Add > New Item. Select Web from the left panel, then select “Razor View” from templates panel and name it ToDo.cshtml. Put the following code in the file.

@page "/todo"
@using ASPNETBlazorCRUDApp.Shared
@using Microsoft.AspNetCore.Blazor.Browser.Interop
@inject HttpClient Http

<h1>ToDo List</h1>

<div>
    <div class="row">
        <div class="col-sm-1">
            <p>Item:</p>
        </div>
        <div class="col-sm-4">
            <input id="todoName" placeholder="Item Name" @bind(itemName)>
        </div>
    </div>
    <br />
    <div class="row">
        <div class="col-sm-1">
            <button class="btn btn-info" id="btnAdd" @onclick(async () => await AddToDo())>Add</button>
        </div>
        <div class="col-sm-2">
            @if (todos != null && todos.Count > 0)
            {
                <button class="btn btn-danger" @onclick(async () => await DeleteAllToDos())>Delete All</button>
            }
        </div>
    </div>
</div>
<br /><br />
@if (todos == null)
{
    <p><em>Loading...</em></p>
}
else
{
    @if (todos.Count > 0)
    {
        <table class='table table-striped table-bordered table-hover table-condensed' style="width:80%;">
            <thead>
                <tr>
                    <th style="width: 40%">Name</th>
                    <th style="width: 40%">Edit</th>
                    <th style="width: 20%">Delete</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var todo in todos)
                {
                    <tr>
                        <td>
                            <span id="spn_@todo.ID">@todo.Item</span>
                            <input id="txt_@todo.ID" @bind(UpdateItemName) style="display:none;">
                        </td>
                        <td>
                            <button id="btnEdit_@todo.ID" class="btn btn-primary" @onclick(() => EditToDo(todo.ID, todo.Item))>Edit</button>
                            <button id="btnUpdate_@todo.ID" style="display:none;" class="btn btn-success" @onclick(async () => await UpdateToDo(todo.ID))>Update</button>
                            <button id="btnCancel_@todo.ID" style="display:none;" class="btn btn-primary" @onclick(() => CancelToDo(todo.ID))>Cancel</button>
                        </td>
                        <td><button class="btn btn-danger" @onclick(async () => await DeleteToDo(todo.ID))>Delete</button></td>
                    </tr>
                }
            </tbody>
        </table>
    }
}

<script>
    Blazor.registerFunction('ShowControl', (id, item, bShow) => {
        if (bShow) {
            var txtInput = document.getElementById("txt_" + id);
            document.getElementById("spn_" + id).style.display = "none";
            txtInput.style.display = "";
            txtInput.value = item;
            txtInput.focus();
            document.getElementById("btnEdit_" + id).style.display = "none";
            document.getElementById("btnUpdate_" + id).style.display = "";
            document.getElementById("btnCancel_" + id).style.display = "";
        }
        else {
            document.getElementById("spn_" + id).style.display = "";
            document.getElementById("txt_" + id).style.display = "none";
            document.getElementById("btnEdit_" + id).style.display = "";
            document.getElementById("btnUpdate_" + id).style.display = "none";
            document.getElementById("btnCancel_" + id).style.display = "none";
        }
        return true;
    });
</script>
@functions {
        string itemName;
        string UpdateItemName;

        IList<ToDoList> todos = new List<ToDoList>();

protected override async Task OnInitAsync()
    {
        await Refresh();
    }

    private async Task Refresh()
    {
        todos = await Http.GetJsonAsync<ToDoList[]>("/api/ToDo");
        StateHasChanged();
    }

    private async Task AddToDo()
    {
        if (!string.IsNullOrEmpty(itemName))
        {
            await Http.SendJsonAsync(HttpMethod.Post, "/api/ToDo", new ToDoList
            {
                Item = itemName,
            });

            itemName = "";
            await Refresh();
        }
    }

    private async Task UpdateToDo(int id)
    {
        if (!string.IsNullOrEmpty(UpdateItemName))
        {
           await Http.SendJsonAsync(HttpMethod.Put, $"/api/ToDo/{id}", new ToDoList
            {
                ID = id,
                Item = UpdateItemName,
            });

            await Refresh();
            //UpdateItemName = "";

            RegisteredFunction.Invoke<bool>("ShowControl", id.ToString(), "", false);
        }
    }

    private async Task DeleteToDo(int id)
    {
        await Http.DeleteAsync($"/api/ToDo/{id}");
        await Refresh();
    }

    private void EditToDo(int id, string itemName)
    {
        RegisteredFunction.Invoke<bool>("ShowControl", id.ToString(), itemName, true);
    }

    private void CancelToDo(int id)
    {
        RegisteredFunction.Invoke<bool>("ShowControl", id.ToString(), "", false);
    }

    private async Task DeleteAllToDos()
    {
        foreach (var c in todos)
        {
            await Http.DeleteAsync($"/api/ToDo/{c.ID}");
        }

        await Refresh();
    }
}

Let’s understand this code. The above code can be divided into 3 sections (HTML, JavaScript and C#). We’ll take a look at each of them in details. before, we do that, let’s understand the very first 4 lines.

@page "/todo"
@using ASPNETBlazorCRUDApp.Shared
@using Microsoft.AspNetCore.Blazor.Browser.Interop
@inject HttpClient Http

  • We are defining the route for this page using @page directive. So appending “/todo” to base URL will redirect to this component.
  • Including the ASPNETBlazorCRUDApp.Shared namespace as ToDoList class is used.
  • The namespace Microsoft.AspNetCore.Blazor.Browser.Interop is included to call JavaScript from the Blazor code. Currently, WebAssembly and therefore Mono and Blazor have no direct access to the browser’s DOM API. Read this post for a detailed information.
  • We are also injecting HTTPClient dependency to call the server-side API.

Now,let’s understand the each section.

HTML

The HTML part is quite simple if you are familiar with Razor syntax. It has a table and a couple of buttons. The @bind is used for two-way data-binding. Read more about data binding here. The @onclick is used to call the method on the click of the button.

JavaScript

Blazor directly can’t call JavaScript function. From learn-blazor.com

To call other JS libraries or your own custom JS/TS code from .NET, the current approach is to register a named function in a JavaScript/TypeScript file, e.g.:

// This is JavaScript
Blazor.registerFunction('doPrompt', message => {
  return prompt(message);
});

… and then wrap it for calls from .NET:

// This is C#
public static bool DoPrompt(string message)
{
    return RegisteredFunction.Invoke<bool>("doPrompt", message);
} 

The JavaScript function named ShowControl defined in the code, controls the visibility of the HTML elements. This is called from C# code on click of Edit, Update and Cancel button.

C#

At the bottom of the page, there is a @functions section which contains code for making server-side web api call for CRUD operations, calling JavaScript and refreshing the ToDo list. The only new thing here is the way C# makes a call to JavaScript ShowControl function on Edit, Update and Cancel button. Other than that it’s simple and familiar code.

Lastly, we need to add the “ToDo” component link in the navigation bar. To do that, open the NavMenu.html file located inside the Shared folder in the client app and add the following code just after the “Fetch Data” link.

<li>
    <NavLink href="/todo">
        <span class='glyphicon glyphicon-list-alt'></span> To Do
    </NavLink>
</li>

That’s it. Run the application and you should see the following.

 

Final Thoughts

These are still early days for Blazor, but we can start building component-based web apps that run in the browser with .NET. Initially, you would find difficult to make progress. Microsoft has promised to bring many new features and improvements planned for future updates. Let’s hope that soon there will be an official documentation and great community support. In this post, we learned about the new .NET framework – Blazor and also created a simple CRUD application using Blazor.

I am really excited to play with this, so more blog post coming up on Blazor. Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.



ASP.NET Core Hosting :: How to Produce HTTP Response in ASP.NET Core Outside of MVC Controllers

clock March 26, 2019 13:05 by author Jervis

ASP.NET Core 2.1 introduced support for a little (or, should I say, not at all) documented feature called IActionResultExecutor<T>. It allows us to use some of the action results -those that we are used to from MVC controllers – outside of the controller context, so for example from a middleware component.

Controller helper methods

The most important of the ActionResult family is the ObjectResult – which internally handles content negotiation – so determines what media type is suitable for the response, and serializes the response accordingly using the selected formatter (JSON, XML, Protobuf or whatever you support). The typical controller, using an ObjectResult might look like this:

[HttpGet("contacts")]
public IActionResult Get()
{
    var contacts = new[]
    {
        new Contact { Name = "Jervis", City = "Dallas" },
        new Contact { Name = "Not Jervis", City = "Not Dallas" }
    };
    // will do content negotiation
    return new ObjectResult(contacts);
}

We could also return a POCO directly from the action, but the framework would still end up using ObjectResult to process that, so ultimately it is still the same thing.

[HttpGet("contacts")]
public IEnumerable<Contact> Get()
{
    var contacts = new[]
    {
        new Contact { Name = "Jervis", City = "Dallas" },
        new Contact { Name = "Not Jervis", City = "Not Dallas" }
    };
    // will do content negotiation
    return contacts;
}

Finally, and this is what this post is about, you could replace our usage of ObjectResult, or the POCO, with a call to Ok() on the base controller:

[HttpGet("contacts")]
public IActionResult Get()
{
    var contacts = new[]
    {
        new Contact { Name = "Jervis", City = "Dallas" },
        new Contact { Name = "Not Jervis", City = "Not Dallas" }
    };
    // will do content negotiation
    return Ok(contacts);
}

This is really still the same as before, because Ok() actually uses ObjectResult under the hood, it’s just expressed in a slightly different way. Now, if you have done any work with MVC controllers, I am sure you are used to those helper methods that are there on the the framework’s ControllerBase, like our Ok() or other – for example Unauthorized() or File(), to name just two of them.

They come in many, many variants (the base controller is 2700+ lines of code…), and are used as shortcuts into the many ActionResults that the framework offers. You can find a full list here. From my experience with various ASP.NET Core MVC projects, I would say that these helper methods are extremely popular among developers – they make the code very concise. They also hide certain complexity level of dealing with producing the HTTP responses, yet still make it very obvious to understand what is going on.

Controller feeling, without a controller

What we recently introduced into WebApiContrib.Core is a similar set of methods as found on the base controller, but ported as extension methods on top of HttpContext. This is done as a combination of IActionResultExecutor<T> features and “manual” response creation. Meaning we either mimic the behavior of the method from base controller by manually crafting the HTTP response, setting headers, status codes and so on, or we really reach into the IActionResultExecutor<T> infrastructure and invoke the relevant action result from the MVC framework.

The end result is very neat, and you get very similar helper method set that you can now enjoy from your non-controller code – primarily middleware but potentially some other places too.

So imagine you are creating a “lightweight” HTTP endpoint using the new Endpoint Routing feature. You can now use the new helper methods to produce the response. Here is a full sample application setup:

public static async Task Main(string[] args) =>
    await WebHost.CreateDefaultBuilder(args)
        .ConfigureServices(s =>
        {
            s.AddRouting();            

            // necessary to wire in ActionResults
            // and content negotiation
            // you can manually register other formatters here
            // for example Messagepack or Protobuf
            s.AddMvc(); 

            // note: due to the current state of ASP.NET Core 3.0 (preview3)
            // you need to manually call: s.AddMvc().AddNewtonsoftJson()
            // to use JSON formatter. This will be fixed in the future in the framework
        })
        .Configure(app =>
        {
            app.UseRouting(r =>
            {
                r.MapGet("contacts", async context =>
                {
                    var contacts = new[]
                    {
                        new Contact { Name = "Jervis", City = "Dallas" },
                        new Contact { Name = "No Jervis", City = "Not Dallas" }
                    }; 

                    // from WebApiContrib.Core
                    // will do content negotiation
                    await context.Ok(contacts);
                });
            });
        }).Build().RunAsync();

In order to make this work, the only thing that is needed, is that it’s necessary to have a call to services.AddMvc() in the DI container setup, as the action result and the executor infrastructure is bootstrapped there.

Other than that, this Ok() extension method on HttpContext will behave exactly the same as the Ok() on base controller – including performing the full content negotiation. The example uses endpoint routing from ASP.NET Core 3.0, but it would work from any place in ASP.NET Core request processing pipeline, for example with an IRouter in ASP.NET Core 2.1 or any middleware.

Another example we could quickly look at here, is returning a file stream – instead of dealing with it manually, including all the complexity of async reading of the stream or stuff related to Content-Disposition headers and so on, we can simply use an extension method now:

app.UseRouting(r =>
{
    r.MapGet("download", async context =>
    {
        // some file path
        var path = Path.GetFullPath(Path.Combine("files", "myfile.pdf")); 

        // from WebApiContrib.Core
        await context.PhysicalFile(path, "application/pdf");
    });
});

In this particular case, the helper method would end up using an action result, a PhysicalFileActionResult, which will take care of reading the file in a non-blocking way and make sure all HTTP response details are correctly handled. And just like before, PhysicalFile() mimics a corresponding method from the MVC base controller.

The full list of the available extension methods can be found below. And I really encourage you to try them – they are part of WebApiContrib.Core 2.2.0.

Task Accepted(this HttpContext c, Uri uri, object value);
Task Accepted(this HttpContext c, string uri, object value);
Task Accepted(this HttpContext c, string uri);
Task Accepted(this HttpContext c, Uri uri);
Task Accepted(this HttpContext c, object value);
Task Accepted(this HttpContext c);
Task BadRequest(this HttpContext c);
Task BadRequest(this HttpContext c, object error);
Task BadRequest(this HttpContext c, ModelStateDictionary modelState);
Task Conflict(this HttpContext c, object error);
Task Conflict(this HttpContext c, ModelStateDictionary modelState);
Task Conflict(this HttpContext c);
Task Content(this HttpContext c, string content, MediaTypeHeaderValue contentType);
Task Content(this HttpContext c, string content, string contentType, Encoding contentEncoding);
Task Content(this HttpContext c, string content, string contentType);
Task Content(this HttpContext c, string content);
Task Created(this HttpContext c, string uri, object value);
Task Created(this HttpContext c, Uri uri, object value);
Task File(this HttpContext c, string virtualPath, string contentType);
Task File(this HttpContext c, Stream fileStream, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task File(this HttpContext c, Stream fileStream, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task File(this HttpContext c, Stream fileStream, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task File(this HttpContext c, string virtualPath, string contentType, string fileDownloadName);
Task File(this HttpContext c, string virtualPath, string contentType, string fileDownloadName, bool enableRangeProcessing);
Task File(this HttpContext c, string virtualPath, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task File(this HttpContext c, string virtualPath, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task File(this HttpContext c, Stream fileStream, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task File(this HttpContext c, string virtualPath, string contentType, bool enableRangeProcessing);
Task File(this HttpContext c, Stream fileStream, string contentType, string fileDownloadName, bool enableRangeProcessing);
Task File(this HttpContext c, byte[] fileContents, string contentType, string fileDownloadName);
Task File(this HttpContext c, Stream fileStream, string contentType, bool enableRangeProcessing);
Task File(this HttpContext c, Stream fileStream, string contentType);
Task File(this HttpContext c, byte[] fileContents, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task File(this HttpContext c, byte[] fileContents, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task File(this HttpContext c, byte[] fileContents, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task File(this HttpContext c, byte[] fileContents, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task File(this HttpContext c, byte[] fileContents, string contentType, string fileDownloadName, bool enableRangeProcessing);
Task File(this HttpContext c, string virtualPath, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task File(this HttpContext c, byte[] fileContents, string contentType, bool enableRangeProcessing);
Task File(this HttpContext c, byte[] fileContents, string contentType);
Task File(this HttpContext c, Stream fileStream, string contentType, string fileDownloadName);
Task File(this HttpContext c, string virtualPath, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task Forbid(this HttpContext c);
Task LocalRedirect(this HttpContext c, string localUrl);
Task LocalRedirectPermanent(this HttpContext c, string localUrl);
Task LocalRedirectPermanentPreserveMethod(this HttpContext c, string localUrl);
Task LocalRedirectPreserveMethod(this HttpContext c, string localUrl);
Task NoContent(this HttpContext c);
Task NotFound(this HttpContext c, object value);
Task NotFound(this HttpContext c);
Task Ok(this HttpContext c);
Task Ok(this HttpContext c, object value);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType, string fileDownloadName, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag, bool enableRangeProcessing);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType, DateTimeOffset? lastModified, EntityTagHeaderValue entityTag);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType, string fileDownloadName, bool enableRangeProcessing);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType, string fileDownloadName);
Task PhysicalFile(this HttpContext c, string physicalPath, string contentType, bool enableRangeProcessing);
Task Redirect(this HttpContext c, string url);
Task RedirectPermanent(this HttpContext c, string url);
Task RedirectPermanentPreserveMethod(this HttpContext c, string url);
Task RedirectPreserveMethod(this HttpContext c, string url);
Task StatusCode(this HttpContext c, int statusCode);
Task StatusCode(this HttpContext c, int statusCode, object value);
Task Unauthorized(this HttpContext c);
Task Unauthorized(this HttpContext c, object value);
Task UnprocessableEntity(this HttpContext c, object error);
Task UnprocessableEntity(this HttpContext c, ModelStateDictionary modelState);
Task UnprocessableEntity(this HttpContext c);
Task ValidationProblem(this HttpContext c, ValidationProblemDetails descriptor);
Task ValidationProblem(this HttpContext c, ModelStateDictionary modelStateDictionary);
Task WriteActionResult<TResult>(this HttpContext c, TResult result) where TResult : IActionResult;



ASP.NET Core Hosting :: How to Use StructureMap with ASP.NET Core

clock January 8, 2019 10:26 by author Jervis

This example shows how to use Structuremap dependency injection framework with ASP.NET Core instead of framework-level dependency injection.

ADDING STRUCTUREMAP TO ASP.NET CORE PROJECT

For Structuremap support in ASP.NET Core application we need two NuGet packages

  • StructureMap - core StructureMap package
  • StructureMap.Microsoft.DependencyInjection - adds support for ASP.NET Core

These packages are enough for getting StructureMap up and running.

DEMO SERVICES

For demo purposes let's define primitive messaging service interface and couple of implementations.

public interface IMessagingService
{
    string GetMessage();
}

public class BuiltInDiMessagingService : IMessagingService
{
    public string GetMessage()
    {
        return "Hello from built-in dependency injection!";
    }
}

public class StructuremapMessagingService : IMessagingService
{
    public string GetMessage()
    {
        return "Hello from Structuremap!";
    }
}

We need two implementations to demonstrate how built-in dependency injection is replaced by StructureMap.

DEFINING STRUCTUREMAP REGISTRY

StructureMap uses registry classes for defining dependencies. Direct definitions are also supported but for more complex applications we will write registries anyway. Here is our registry class.

public class MyStructuremapRegistry : Registry
{
    public MyStructuremapRegistry()
    {
        For<IMessagingService>().LifecycleIs(Lifecycles.Container)
                                .Use<StructuremapMessagingService>();
    }
}

ATTACHING STRUCTUREMAP TO ASP.NET CORE APPLICATION

StructureMap is attached to ASP.NET Core when application is starting up. We have to make three updates to ConfigureServices() method of StartUp class:

  • initialize and configure StructureMap container
  • make ConfigureServices return IServiceProvider
  • return IServiceProvider by StructureMap

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddTransient<IMessagingService, BuiltInDiMessagingService>();

    var container = new Container();

    container.Configure(config =>
    {
        config.AddRegistry(new MyStructuremapRegistry());
        config.Populate(services);
    });

    return container.GetInstance<IServiceProvider>();
}

Notice that there is also dependecy definition for framework-level dependency injection. Let's see which implementation wins.

TRYING OUT STRUCTUREMAP WITH ASP.NET CORE 2.0

Let's make some minor updates to Home controller and Index view to get message from injected service and display it on home page of sample application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ASPNETCoreTemplate.Services;
using Microsoft.AspNetCore.Mvc;

namespace ASPNETCoreTemplate.Controllers
{
    public class HomeController : Controller
    {
        private readonly IMessagingService _messagingService;

        public HomeController (IMessagingService messagingService)
        {
            _messagingService = messagingService;
        }

        public IActionResult Index()
        {
            ViewData["Message"] = _messagingService.GetMessage();

            return View();
        }

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



ASP.NET Core Hosting :: How to Fix Error "An error occurred while starting the application" in ASP.NET Core

clock November 9, 2018 09:43 by author Jervis

 

Previously, we have written tutorial about how to fix 502.5 error that you face when publishing your ASP.NET Core application. Another issue that you might face when publishing your .net Core application is:

“An error occurred while starting the application.  .NET Framework <version number> | Microsoft.AspNetCore.Hosting version <version number> | Microsoft Windows <version number>”

It looks like:

 

What happened?

It basically means something really bad happened with your app.  Some things that might have gone wrong:

  • You might not have the correct .NET Core version installed on the server.
  • You might be missing DLL’s

  • Something went wrong in your Program.cs or Startup.cs before any exception handling kicked in

Event Viewer (Probably) Won’t Show You Anything

If you’re running on Windows and behind IIS, you might immediately go to the Event Viewer to see what happened based on your previous ASP.NET knowledge.  You’ll notice that the error is not there.  This is because Event Logging must be wired up explicitly and you’ll need to use the Microsoft.Extensions.Logging.EventLog package, and depending on the error, you might not have a chance to even catch it to log to the Event Viewer.

How to figure out what happened (if running on IIS)

Instead of the Event Viewer, if you’re running behind IIS, we can log the request out to a file.  To do that:

  1. Open your web.config
  2. Change stdoutLogEnabled=true
  3. Create a logs folder
    - Unfortunately, the AspNetCoreModule doesn’t create the folder for you by default. If you forget to create the logs folder, an error will be logged to the Event Viewer that says: Warning: Could not create stdoutLogFile \\?\YourPath\logs\stdout_timestamp.log, ErrorCode = -2147024893.
    -
    The “stdout” part of  the value “.\logs\stdout” actually references the filename not the folder.  Which is a bit confusing.
  4. Run your request again, then open the \logs\stdout_*.log file

Note – you will want to turn this off after you’re done troubleshooting, as it is a performance hit.

So your web.config’s aspNetCore element should look something like this

 <aspNetCore processPath=”.\YourProjectName.exe” stdoutLogEnabled=”true” stdoutLogFile=”.\logs\stdout” />

Doing this will log all the requests out to this file and when the exception occurs, it will give you the full stack trace of what happened in the \logs\stdout_*.log file

 

 

Hope this helps. In case, you need ASP.NET Core hosting, you can always try our services start from $1.00/month.

 



Cheap ASP.NET 4.5 Hosting

We’re a company that works differently to most. Value is what we output and help our customers achieve, not how much money we put in the bank. It’s not because we are altruistic. It’s based on an even simpler principle. "Do good things, and good things will come to you".

Success for us is something that is continually experienced, not something that is reached. For us it is all about the experience – more than the journey. Life is a continual experience. We see the Internet as being an incredible amplifier to the experience of life for all of us. It can help humanity come together to explode in knowledge exploration and discussion. It is continual enlightenment of new ideas, experiences, and passions


Author Link

 photo ahp banner aspnet-01_zps87l92lcl.png

 

Corporate Address (Location)

ASPHostPortal
170 W 56th Street, Suite 121
New York, NY 10019
United States

Tag cloud

Sign in