ASP.NET Core 2: Model Validation Part 2

download.jpgIn Part 1, we covered simple model validation where the entire model is posted back in a form.

In this tutorial, we cover how to validate just one field on the server as well.

Create a simple Model, on this class we have a National ID field. The possible values for this ID are too many to store or calculate on the client so need to be verified on the server without posting the entire form back.

public class PersonModel
{
    [Remote"VerifyNationalID""Home")] 
    public int NationalID { getset; }
}

On the Controller add a VerifyNationalID method on the Home controller:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View(new PersonModel());
    }
 
    public IActionResult VerifyNationalID(int nationalId)
    {
        if (nationalId == 12345) return new JsonResult(true);
        return new JsonResult("That ID does not exist in the database");
    }

On the client add a simple text box and submit button. Use the TagHelpers to connect to the model’s NationalID field

<!-- Add the validation scripts-->
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.2.0.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.16.0/jquery.validate.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"></script>
 
 
<form action="/Home/VerifyEntireForm" method="post">
    <div class="form-group">
        <label asp-for="NationalID" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="NationalID" class="form-control" />
            <span asp-validation-for="NationalID" class="text-danger"></span>
        </div>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

When run, a warning will appear when the user leaves the field. The plumbing is handled by jQuery and ASP.NET CORE.

validation2.png

 

 

Advertisements

ASP.NET Core 2: Model Validation Part 1

download.jpgIn this tutorial, we’ll show you how to add some simple custom business logic to a model so that values can be verified on the server via a post back.

Business Logic: Only children are allowed in this model. A child is under 13.

Our Model is simple and has a ChildOnly attribute which we’ll create next:

public class PersonModel
{
    [ChildOnly] 
    public int Age { getset; }
}

Next we create the business logic-holding attribute. The function IsValid() is what is called by ASP.NET Core’s validation system and is fairly simple:

public class ChildOnlyAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        //Get the model we are trying to validate
        if (validationContext?.ObjectInstance is PersonModel model)
        {
            //Only Kids are allowed (under 13)
            if (model.Age > 12)
            {
                return new ValidationResult("Person is too old and is not considered a child");
            }
        }
        return ValidationResult.Success;
    }
}

Now that we have the model and the business logic ready on the server, let’s add some simple HTML. The TagHelpers will convert the purple commands into properly bound HTML.

<form action="/Home/Verify" method="post">
    <div class="form-group">
        <label asp-for="Age" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input asp-for="Age" class="form-control" />
            <span asp-validation-for="Age" class="text-danger"></span>
        </div>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

On our controller we have the Actions to both present the form and verify it on a post back.

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return View(new PersonModel());
    }
 
    public IActionResult Verify(PersonModel model)
    {
        if (!ModelState.IsValid)
        {
            return View("Index",model);
        }
        return new ContentResult()
        {
            Content = "Looks Good"
        };
    }

Here’s what it looks like when run:

home verify.png

 

ASP.Net Core 2: TagHelper Part 3: Custom html attributes

tag 3 logo.pngIn Part 1 you learned how to create a simple email TagHelper for ASP.Net Core. We will expand on that project and add a TagHelper which will add values to the html class attribute of any div.

Our goal is to write this in our Razor pages:
<div asp-button=“true”>My Button</div>

and have this Html created:
<div class=“btn btn-primary”>My Button</div>

Step 1: Using the project you wrote in Part 1 or Part 2, add a new class called ButtonTagHelper.cs

/// <summary>
/// Only Divs with the attribute asp-button are affected
/// </summary>
[HtmlTargetElement("div", Attributes = "asp-button")]
public class ButtonTagHelper : TagHelper
{
    /// <summary>
    /// The asp-button attribute will get auto-mapped to this property
    /// </summary>
    [HtmlAttributeName("asp-button")]
    public string Button { getset; }
 
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        //If there was an asp-button attribute add a bootstrap btn class
        if (this.Button == "true")
        {
            //Get the current value of the class attribute
            var currentClassValue = "";
            if (output.Attributes.ContainsName("class"))
            {
                currentClassValue = output.Attributes["class"].Value.ToString();
                output.Attributes.Remove(output.Attributes["class"]);
            }
 
            //Add a new class attribute with the previous values
            output.Attributes.Add("class""btn btn-primary " + currentClassValue);
        }
    }
}

Let’s break this down:

[HtmlTargetElement(“div”, Attributes = “asp-button”)]

This tells ASP.NET Core that the following TagHelper is to be applied to an div with an asp-button attribute.

[HtmlAttributeName(“asp-button”)]
public string Button { get; set; }

A bit of magic here. ASP.NET Core will convert the value of the asp-button attribute and will add it to the property. The property must be public.


Here’s the result:

taghelper3.png

ASP.Net Core 2: TagHelper Part 2: Display downloaded Quotes

quote-clipart-9TpbXMnnc.pngIn Part 1 you learned how to create a simple email TagHelper for ASP.Net Core. We will expand on that project and add a TagHelper.


Step 1: Add a new class called RandomQuoteTagHelper to your web project

public class RandomQuoteTagHelper :TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        //The Html Tag will be a div
        output.TagName = "div";
 
        var html = "";
        using (var w = new WebClient())
        {
            //Get a random QUOTE
            var url = "http://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1";
 
            //Convert the quote to a dynamic object so we can get the Quote text out
            dynamic quote = JsonConvert.DeserializeObject(w.DownloadString(url));
            html = quote[0].content;
        }
        //Add Html quote to the Div
        output.Content.SetHtmlContent(html);
    }
}

Step 2: Add the Tag Helper to a view

<random-quote></random-quote>

 


Here’s how it looks when run:

taghelper2.png

ASP.NET Core 2: TagHelpers Part 1

images.jpgTagHelpers let you simplify the markup in your Razor pages and improve readability.

Which would you rather have on your Razor Page?

<email-support></email-support>

or

taghelper1.png

Step 1: Create a new ASP.NET Core project, any template will do. Call it TagThis

Step 2: Add a class called EmailSupport.cs to the web project

This class tells ASP.NET Core how to render the custom tag and is fairly self-explanatory in this basic example

public class EmailSupport :TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        //The Html Tag will be an Anchor
        output.TagName = "a";
 
        //Add the link and css class to the anchor tag
        output.Attributes.Add(new TagHelperAttribute("href","mailto:Support@IanVink.com"));
        output.Attributes.Add(new TagHelperAttribute("class""btn btn-primary"));
 
        //Add text to the link
        output.Content.SetHtmlContent("Email Support");
    }
}

Step 3: Edit the _ViewImports.cshtml file and tell it to add all Tag Helpers from the TagThis assembly. Notice the “*”

@addTagHelper *, TagThis

Step 4: Add Bootstrap and FontAwesome css to your _Layout.cshtml to make it look pretty

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" >
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

Step 5: Add this markup to a page.

Warning: Your TagHelper class, if its name has CaSe, must be referenced in lowercase with a ‘-‘ separating the words. For example, EmailSupport becomes <email-support>.

<email-support></email-support>

 


The result:

taghelperemail.png

Beautiful button, beautiful markup

ASP.NET Core 2: Using SQLite as a light weight database

SQLite370.svg.pngAzure is a great place to store your data of any size, but sometimes that may not be possible for a number of reasons. In this article I’ll show you how to use Microsoft Entity Framework Core (EF) and SQLite to create and store a small amount of data.

This code is a bare-bones example. It doesn’t include important features like error handling or DI.

Note: There is no database file. EF Core will create the SQLite database file for you.

Step 1: Create any simple ASP.NET Core site via the (File | New) menu

Step 2: Add these NuGet packages

  1. Microsoft.EntityFrameworkCore
  2. Microsoft.EntityFrameworkCore.Sqlite
  3. Microsoft.EntityFrameworkCore.Sqlite.Core

Step 3: DbContext

All of the magic takes place in a single simple data class. Add this to your solution:

public class SimpleDataStorageDbContext
{
    public SimpleDataStorage(){}
 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        //Set the filename of the database to be created
        optionsBuilder.UseSqlite("Data Source=db.sqlite");
    }
 
    public DbSet<Cat> Cats { getset; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
 
        //Define the Table(s) and References to be created automatically
        modelBuilder.Entity<Cat>(b =>
        {
            b.HasKey(e => e.Id);
            b.Property(e => e.Id).ValueGeneratedOnAdd();
            b.Property(e => e.Name).IsRequired().HasMaxLength(255);
            b.ToTable("Cats");
        });
    }
}

What’s very interesting here is that the database doesn’t exist, the class SimpleDataStorage tells EF how and where to create it.

Step 4: Create the database and tables in Startup.cs

public class Startup
{
   public Startup()
    {
        using (var client = new SimpleDataStorage())
        {
            //Create the database file at a path defined in SimpleDataStorage
            client.Database.EnsureCreated();
            //Create the database tables defined in SimpleDataStorage
            client.Database.Migrate();
        }
    }

Step 5: Add Cats to the database!

We can now access the database anywhere in code

public IActionResult Index(SimpleDataStorage db)
{
    for (int i = 0; i < 1000; i++)
    {
        db.Cats.Add(new Cat() {Name = "Caty McCat: " + i}); 
    }
    db.SaveChanges(true);
    return View();
}


Resources: A good SQLite database editor

 

ASP.NET Core 2: Injecting Services into Razor pages

cat2.pngInject all the things.

Injecting dependencies into Razor pages is a new feature in ASP.NET Core designed to help with testing and simplicity.

Are cat pictures funny? The article will help answer that age-old question using a service injected into a Razor page.

Step 1: Create a service and interface

public class FunnyCatManagerIFunnyCat
{
    public string AreCatsFunny => "Yes";
}
 
public interface IFunnyCat
{
    string AreCatsFunny { get;}
}

Step 2: Add the IFunnyCat interface to ASP.NET Core’s dependency injection. Edit the Startup.cs file and add this:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
         services.AddTransient(typeof(IFunnyCat), typeof(FunnyCatManager));

Step 3: Inject the IFunnyCat implementation into a Razor page

@inject IFunnyCat CatManager
Are Cats Funny? <b>@CatManager.AreCatsFunny</b>

The result looks like this:

cat.png

Cats are indeed funny