Friday, July 21, 2023

ASP.NET Core Razor Pages Concept Building Exercises

Ex. Create a web project using ASP.NET Core Empty template. Create a form with a textbox and submit button without using any razor page. When user clicks the button, text of textbox is displayed in uppercase.

Solution. Create web project using ASP.NET Core Empty template. Edit the Startup class as given below to create form.
Note that HttpResponse object property ContentType is set "text/html" to render form otherwise html tags will be treated as plain text because by default ContentType is "text/plain". Form is rendered to the client browser when app runs by using MapGet. Now, if client clicks the button, the request again goes to the server. Note the form method is POST, so MapPost method is used. Server reads the Request data from the textbox of the form and displays it in uppercase as Response.
Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Text;

namespace RPExercises
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<form method='post'>");
            sb.Append("<br/>");
            sb.Append("<input type='text' name='txtname' id='txtname' />");
            sb.Append("<br/>");
            sb.Append("<input type='submit' name='btnSend' id='btnSend' value='Click' />");
            string frm1 = sb.ToString();

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    var res = context.Response;
                    res.ContentType = "text/html";
                    await res.WriteAsync(frm1);
                });

                endpoints.MapPost("/", async context =>
                {
                    var data= context.Request.Form["txtname"];
                    await context.Response.WriteAsync(data.toUpper());
                    await context.Response.WriteAsync("DONE");
                });
            });
        }
    }
}

Ex. Create a web project using ASP.NET Core Empty template. Edit the Startup class to add a middleware which checks the port number of the server in Request object, and if port number is okay then allows static files of the server. Write a message to the client that the request is successfully accepted.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Edit the Startup class as given below to conditionally allow static files.
Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

namespace RPExercises
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.MapWhen( ctx=>ctx.Request.Host.Port == 44391, configuration =>
            {
                configuration.UseStaticFiles();
                configuration.Run(async ctx => { await ctx.Response.WriteAsync("Host port number is 44391. Static files enabled. Create wwwroot and place a static file there and test it."); });
            }
            );
        }
    }
}

Ex. Create a web project using ASP.NET Core Empty template. Edit the Startup class to read the configuration from appsettings.json file.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Edit the Startup class as given below to read write the configuration from appsettings.json file. The appsettings file is used to set log levels or constants like company info. Microsoft.Extensions.Configuration.IConfiguration type is used to read configuration key-value pairs etc. from different sources like appsettings file or environment variables. Use dependency injection to inject the service of IConfiguration in the Startup class. In the code, GetSection method is used to read the value of a section from the appsettings file. The GetChildren method is used to read the value of each section.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}
Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;

namespace RPExercises
{
    public class Startup
    {
        private readonly IConfiguration configuration;
        public Startup(IConfiguration configuration)
        {
            this.configuration = configuration;
        }
        public void Configure(IApplicationBuilder app)
        {
            app.Run(async ctx =>
            {
                // flattening json
                string fromAppsettings = configuration.GetSection("Logging:LogLevel:Microsoft").Value;
                await ctx.Response.WriteAsync("From appsettings: " + fromAppsettings);
                // read all configuration keys
                string foo = "";
                var sections = configuration.GetChildren();
                foreach (var se in sections)
                {
                    foo += se.Key + "\n";
                }
                await ctx.Response.WriteAsync(foo);
               
            });
        }
    }
}

Ex. Create a web project using ASP.NET Core Empty template. Edit the Startup class to include logging in the Startup class.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Edit the Startup class as given below. Note that ILogger<Startup> is used in Configure method as parameter to inject the ILogger service. The ILogger is framework service which is built-in and service is automatically provided. Run the app and check if the log is working.
Startup class

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddLogging(options =>
            {
                options.ClearProviders();
                options.AddConsole().AddEventLog();
            });
        }
        public void Configure(ILogger<Startup> logger)
        {
            logger.LogInformation("This is simple log message");
        }
    }
}

Q. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Read the configuration from appsettings.json file in the Index page.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Edit the Startup class and Index page as given below and run the app.

Index Page

@page
@inject Microsoft.Extensions.Configuration.IConfiguration config

<h1>@config.GetSection("Logging:LogLevel:Microsoft").Value</h1>
<h1>@config.GetSection("Logging:LogLevel:Microsoft.Hosting.Lifetime").Value</h1>
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}
Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); });
        }
    }
}

Q. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Add a property in the IndexModel class. Read the model properties of IndexModel class in the Index page.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Edit the Startup class and Index page as given below and run the app. Properties called myname and colors are added in the ModelIndex class. @Model is used to read these properties in the Index razor page. Note that @Model object can be used to read all values from HttpContext.
IndexModel class

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

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public string myname { get; set; } = "Ajeet Kumar";
        public List<string> colors = new List<string>()
        {
            "red", "green", "blue","cyan"
        };
        public void OnGet()
        {
        }
    }
}

Index Page

@page
@model RPExercises.Pages.IndexModel


<h2>@Model.HttpContext.Response.ContentType</h2>
<h2>@Model.HttpContext.Response.Headers.FirstOrDefault()</h2>
<h2>@Model.Url.IsLocalUrl("/happy.jpg")</h2>
<h2>@Model.myname</h2>
@foreach (var color in Model.colors)
{
    <h3>@color</h3>
}

Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); });
        }
    }
}

Q. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Read the web host environment variables of the application.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Edit the Startup class and Index page as given below. Use IWebHostEnvironment built-in framework object to read the web host environment variables of the application in Razor pages or in a class.

Index Page

@page
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment  env

@env.ApplicationName <br/>
@env.WebRootPath <br/>
@env.ContentRootPath <br/>
@env.EnvironmentName <br/>

@{
    var f = env.WebRootFileProvider.GetFileInfo("happy.jpg").PhysicalPath;
}
@f
Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Text;

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(env.ApplicationName);
            sb.Append("\n");
            sb.Append(env.EnvironmentName);
            sb.Append("\n");
            sb.Append(env.ContentRootPath);
            sb.Append("\n");
            sb.Append(env.WebRootPath);
            sb.Append("\n");
            sb.Append(env.IsEnvironment("Development").ToString());
            sb.Append("\n");
            // get folder contents
            var provider = env.ContentRootFileProvider;
            var dirContents = provider.GetDirectoryContents("~/");
            foreach (var item in dirContents)
            {
                if (item.IsDirectory)
                {
                    sb.Append(item.PhysicalPath);
                    sb.Append("\n");
                }
            }
            // get any file info
            string appsetting = provider.GetFileInfo("~/appsettings.json").PhysicalPath;
            sb.Append(appsetting);
            string info = sb.ToString();
            
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/infos", async ctx => await ctx.Response.WriteAsync(info));
                endpoints.MapRazorPages(); }
            );
        }
    }
}

Ex. Create an ASP.NET Core Razor page app. Add a razor page called Index and add an anchor tag on it. When the link is clicked, appsettings file key-value pairs are read and displayed on the page.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Edit the Startup class and Index page as given below and run the app.
Appsettings file

{
  "Company": "Appliedk",
  "Address": {
    "City": "Delhi",
    "Location":"DDA Flats",
    "StreetNo": 400
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.AspNetCore": "Debug",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<a asp-page="Index" asp-page-handler="FromSettings"> Get data </a>
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Configuration;
using System.Text.Json;
using System.Threading.Tasks;

namespace RPExercises.Pages
{
    public class Address
    {
        public string City { get; set; }
        public string Location { get; set; }
        public int StreetNo { get; set; }
    }
    public class IndexModel : PageModel
    {
        private readonly IConfiguration _cfg;

        public IndexModel(IConfiguration configuration)
        {
            _cfg = configuration;
        }
        public async Task<JsonResult> OnGetFromSettingsAsync()
        {
      
            string city = _cfg.GetValue<string>("Address:City");
            string location = _cfg.GetValue<string>("Address:Location");
            int streetNo = _cfg.GetValue<int>("Address:StreetNo");
            await Task.Delay(500);
            Address address = new Address()
            {
                City=city, Location=location, StreetNo=streetNo
            };
            // return new JsonResult(JsonSerializer.Serialize($"City: {city}Location: {location} Street:{streetNo}"));
            
            return new JsonResult(JsonSerializer.Serialize(address));
        }
    }
}
Startup class

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

Ex. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Read the appsettings.json.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Edit the Startup class and Index page as given below and run the app.

{
  "Company": "Appliedk",
  "Address": {
    "City": "Delhi",
    "Location":"DDA Flats",
    "StreetNo": 400
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.AspNetCore": "Debug",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<a asp-page="Index" asp-page-handler="FromSettings"> Get data </a>
<br/>
@Model.Message
IndexModel class

using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Configuration;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public string Message { get; set; }
        private readonly IConfiguration _cfg;

        public IndexModel(IConfiguration configuration)
        {
            _cfg = configuration;
        }
        public void OnGetFromSettingsAsync()
        {
            string city = _cfg.GetValue<string>("Address:City");
            string location = _cfg.GetValue<string>("Address:Location");
            int streetNo = _cfg.GetValue<int>("Address:StreetNo");
            Message = $"City: {city} Location: {location} Street:{streetNo}";
        }
    }
}
Startup class

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

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

Ex. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Create a link on the page. When user clicks the links, app reads the configuration from appsettings file using options pattern.

Solution. Open the Visual Studio. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Edit the Startup class and Index page as given below and run the app.
Objective: OptionsPattern class and its characteristics
This class is used to map json file with the class to store key value pairs from configuration source. This class should be named with Options suffix and placed in Options folder.
  • It is a public class and cannot be abstract class.
  • Has only default constructor
  • Properties are public.

Ex. Create a web project using ASP.NET Core. Throw exception in IndexModel class and run the app with and without debug mode.

Add DeveloperExceptionPage middleware and again run the app with and without debug mode.
Solution. Open the Visual Studio. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Edit the Startup class and Index page as given below and run the app.
Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<a asp-page="Index" asp-page-handler="FromSettings"> Get data </a>
<br/>
IndexModel class

using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Configuration;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public void OnGetFromSettingsAsync()
        {
            throw new System.Exception();
        }
    }
}
Startup class

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

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //app.UseDeveloperExceptionPage();
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

Press CTRL+F5 to run the app. Uncomment the line app.UseDeveloperExceptionPage() and Press CTRL+F5.

Ex. Create a web project using ASP.NET Core and add options in DeveloperExceptionPage middleware so that on exceptions, the exception page displays souce code with at most 5 lines around the exception line.

Solution. Open the Visual Studio. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Edit the Startup class and Index page as given below and run the app.
Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System.Net.NetworkInformation;

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseDeveloperExceptionPage(new DeveloperExceptionPageOptions()
            { 
                // get 5 lines up and down from the error line
                SourceCodeLineCount = 5
                //FileProvider = new PhysicalFileProvider(System.IO.Directory.GetCurrentDirectory())
                
            }) ;
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

Ex. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Create a form on it. Place a textbox and submit button on it. When user inputs a number in the textbox and clicks the button, app displays the new number on the page which is 4 more than the input number.

Solution. Open the Visual Studio. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Edit the Startup class, IndexModel and Index page as given below and run the app.
Read the model data in Razor page using @Model or ViewData or TempData etc. ViewData and TempData are used to pass data from model class into razor page while @Model is used to read the model property and HttpContext etc. directly.
Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<form method="post">
    <input type="text" asp-for="number" />
    <button type="submit" >Send Data</button>
</form>
<h3> New number returned  is: @Model.number</h3>
Index Page

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public int number { get; set; }
        public IActionResult OnGet()
        {
            return Page();
        }
        public IActionResult OnPost()
        {
            number = number+4;
            return Page();
        }
    }
}
Startup class

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

namespace RPExercises
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
}

Ex. Create a web project using ASP.NET Core Empty template. Add Pages folder and a Index razor page in it. Create a form on it. Place a textbox and submit button on it. When user inputs a number in the textbox and clicks the button, app displays the new number on the page which is 4 more than the input number using @Model or ViewData or TempData.

Index Page

 public IActionResult OnPost()
        {
            int data = number + 4;
            ViewData["Data"] = data;
            // send data to front page
            return Page();
        }


Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<form method="post">
    <input type="text" asp-for="number" />
    <button type="submit" >Send Data</button>
</form>
<h3> New number returned  is: @ViewData["Data"]</h3>
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public int number { get; set; }
        public IActionResult OnGet(int number)
        {
            int data = number + 4;
            TempData["Data"] = data;
            // send data to front page
            return Page();
        }
    }
}
Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<form method="get">
    <input type="text" asp-for="number" />
    <button type="submit" >Send Data</button>
</form>
<h3> New number returned  is: @TempData["Data"]</h3>

NOTE The bug is it returns 4 initially. Resolve it.

Index Page

@page "{handler?}"
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

@*create a public function in razor page as given below. As we are not using the backend file, the backend function is substituted by this function.*@

@*function definition*@
@functions{

    public Boolean IsClicked { get; set; }

    public void OnGetClicked()
    {
        IsClicked = true;
    }
}

@*consume the function*@
@if(IsClicked){
    <h1> You clicked! Look at the URL. Is it neat?</h1>
}   
else{
    <h1>
        <a asp-page="Index" asp-page-handler="Clicked">Click</a>
    </h1>
   
}
Index Page

@page
@model RPExercises.Pages.IndexModel
<form method="post">
    <input type="text" asp-for="id" /><br />
    <input type="text" asp-for="color" /><br />
    <button type="submit">Send</button>
</form>
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public int id { get; set; }
        [BindProperty]
        public string color { get; set; }
        public void OnPost()
        {
            int x = id;
            string n = color;
        }
    }
}
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public void OnGet()
        {
            ViewData["name"] = "AppliedK";
        }
    }
}
Index Page

@page
@model RPExercises.Pages.IndexModel

<h2>@ViewData["name"]</h2>

Ex.Find company Id and Location on Index page.
IndexModel class

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class Company
    {
        public int Id { get; set; }
        public string Location { get; set; }
    }
    public class IndexModel : PageModel
    {
        public void OnGet()
        {
            Company company = new Company() { Id = 1, Location = "Delhi" };
            ViewData["c1"] = $"Company Id is {company.Id} and location is {company.Location}.";
            ViewData["c2"] = company;
        }
    }
}
Index Page

@page
@model RPExercises.Pages.IndexModel
@{
    var c = @ViewData["co"];
}
<h2>@ViewData["c1"]</h2>
<h2>@ViewData["c2"]</h2>

The following is not working. Why? Error400

Index Page

@page
@model RPExercises.Pages.IndexModel

<form method="post">
    Id: <input type="text" name="Id" id="Id" /> <br/>
    Name: <input type="text" name="Name" id="Name" /><br/>
    <button type="submit">Click</button><br />
</form>

<h2>You sent data: @ViewData["data"]</h2>
IndexModel class

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public void OnPost()
        {
            var id = Request.Form["Id"];
            var name = Request.Form["Name"];

            ViewData["data"] = $"Id:{id}, Name:{name}";
        }
    }
}

Ex. Posted Form Values To Handler Method Parameters 
The following is not working. Why? Error400
My problem is that the OnPost method is not getting called when the submit button is pressed and I cannot figure it out.

Index Page

@page
@model RPExercises.Pages.IndexModel

<form method="post">
    Id: <input type="text" name="Id" id="Id" /> <br/>
    Name: <input type="text" name="Name" id="Name" /><br/>
    <button type="submit">Click</button><br />
</form>

<h2>You sent data: @ViewData["data"]</h2>

IndexModel class

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public void OnPost(int Id, string Name)
        {
            ViewData["data"] = $"Id:{Id}, Name:{Name}";
        }
    }
}

Binding Posted Form Values to PageModel Properties using BindProperty or using BindProperties

IndexModel

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public string Id { get; set; }
        [BindProperty]
        public string Name { get; set; }
        public void OnPost()
        {
            ViewData["data"] = $"Id:{Id}, Name:{Name}";
        }
    }
}
Binding Data From GET Requests 
IndexModel

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public string Id { get; set; }
        [BindProperty]
        public string Name { get; set; }
        public void OnGet()
        {
            ViewData["data"] = $"Id:{Id}, Name:{Name}";
        }
    }
}

Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<form method="post">
    <input type="text" name="number" id="number" />
    <button type="submit">Send Data</button>
</form>
<h3> New number returned  is: @ViewData["n1"]</h3>
IndexModel class

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public void OnPost(string number)
        {
            ViewData["n1"]= int.Parse(number )+ 4;
            
        }
    }
}

ALSO
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public IActionResult OnPost()
        {
            ViewData["n1"] = Request.Form["number"];
            return Page();
        }
    }
}
ALSO
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public void OnPost()
        {
            ViewData["n1"] = Request.Form["number"];
        }
    }
}
Ex. How can you pass query route parameter from Index razor page?
Explain the difference in following anchor route.
Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<a asp-route-param="xyz" >Click1</a><br/>
<a asp-page-handler="Test"  asp-route-param="abc" >Click2</a>
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        public void OnGetTest()
        {

        }
    }
}

Send and Receive the query parameter in IndexModel.
Index Page. 

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<a asp-route-param="xyz" >Click1</a><br/>
<a asp-page-handler="Test"  asp-route-param="abc" >Click2</a>
<br/>
@ViewData["p"]
IndexModel class 

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        string value;
        public void OnGetTest()
        {
           
           if (Request.Query.ContainsKey("param"))
            {
             value =    Request.Query["param"];
            }
            ViewData["p"] = value;
        }
    }
}
Ex. We send the query parameter in anchor tag. Can we send it in the button.
<button type="button" asp-route-param="xyz" >Click1</button><br/>

Ex. Send query parameter from IndexModel into razor page. 
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        string value;
        public IActionResult OnGetParamFromMe()
        {
            return RedirectToPage("Index", new { rv ="RouteValue1"});
        }
    }
}
Index Page

@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers

<a asp-page-handler="ParamFromMe">Click</a>
@{
    if (Request.Query.ContainsKey("rv"))
    {
        <h1>@Request.Query["rv"]</h1>
    }
} 
Ex. Send query parameter from IndexModel into razor page. 
IndexModel class

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public int number1 { get; set; }
        [BindProperty]
        public int number2 { get; set; }
        public IActionResult OnPostSum(int number1 , int number2)
        {
            int sum =  number1 + number2;
            return RedirectToPage("Index", new { rv = sum});
        }
    }
}
Index Page
@page
@model RPExercises.Pages.IndexModel
@addTagHelper *,  Microsoft.AspNetCore.Mvc.TagHelpers
<form method="post">
    <input type="text" asp-for="number1" />
    <br />
    <input type="text" asp-for="number2" />
    <br />
    <input type="submit" asp-page-handler="Sum">
</form>

@{
    if (Request.Query.ContainsKey("rv"))
    {
        <h1>@Request.Query["rv"]</h1>
    }
}
Request.Query.Keys
Request.Query.ContainsKey()
Request.Query.TryGetValue("k1", out var value1);    
Request.Query.Equals(obj)
Request.Query.Count

===========
What is [NotMapped] attribute?
When this attribute is applied on a column, that column is not created in database.

Ex. Create a web project using ASP.NET Core Web App template. Create a form in Index page which displays list of students using Student class. The Student class has properties -Id, Name, Sex and Marks. The form contains a link for each record to navigate to Edit page on which Students details can be updated.

Solution. Open the Visual Studio. Create web project using ASP.NET Core Empty template. Add Index and Edit Razor pages. Create Models folder and create Student model class in Models folder.


using System.Collections.Generic;

namespace RPExercises.Models
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Sex { get; set; }
        public int? Marks { get; set; }

        public static List<Student> GetStudents()
        {
            List<Student> students = new List<Student>()
        {
            new Student(){Id=1, Name="Amit", Sex="Male", Marks=null},
            new Student(){Id=2, Name="Rajesh", Sex="Male", Marks=null},
            new Student(){Id=3, Name="Twinkle", Sex="Female", Marks=null},
            new Student(){Id=4, Name="Tom", Sex="male", Marks=null},
        };
            return students;
        }
    }
}

Update the IndexModel class file as given below. 

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RPExercises.Models;
using System.Collections.Generic;

namespace RPExercises.Pages
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public List<Student> studentsList { get; set; }

        public IActionResult OnGet()
        {
            studentsList = Student.GetStudents();
            return Page();
        }

        public IActionResult OnGetRedirect(int id)
        {
            
            return RedirectToPage("Edit","Edit",id);
        }
        public IActionResult OnPost()
        {

            return Page();
        }
    }
}
Create form on Index page as given below.

@page "{handler?}"
@model RPExercises.Pages.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<form method="post" >
    <table border="1" cellpadding="4">
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Sex</th>
            <th>Marks</th>
            <th>Edit</th>
        </tr>
        @foreach (var student in Model.studentsList)
        {
            <tr>
                <td>@student.Id</td>
                <td>@student.Name</td>
                <td>@student.Sex</td>
                <td>@student.Marks</td>
                <td><a asp-page="Edit" asp-route-id="@student.Id">Edit</a></td>
            </tr>
        }
    </table>
</form>
Create form on Edit Razor page as given below.

@page "{handler?}"
@model RPExercises.Pages.EditModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h2>Update Student Record</h2>
<form method="post">
    <table border="1">
        <tr>
            <td><label asp-for="EditStudent.Id">Id</label></td>
            <td><input asp-for="EditStudent.Id" /></td>
        </tr>
        <tr>
            <td><label asp-for="EditStudent.Name">Name</label></td>
            <td> <input asp-for="EditStudent.Name" /></td>
        </tr>
        <tr>
            <td> <label asp-for="EditStudent.Sex">Sex</label></td>
            <td><input asp-for="EditStudent.Sex" /></td>
        </tr>
        <tr>
            <td><label asp-for="EditStudent.Marks">Marks</label></td>
            <td><input asp-for="EditStudent.Marks" /></td>
        </tr>
        <tr>
            <td colspan="2" style="text-align:right;><input type="submit" /></td>
        </tr>
    </table>
</form>

Create EditModel class as given below.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RPExercises.Models;
using System.Linq;

namespace RPExercises.Pages
{
    public class EditModel : PageModel
    {
        [BindProperty]
        public Student EditStudent { get; set; }
        // get the student record for gievn id
        // and display on Edit page
        public IActionResult OnGet(int id)
        {
            Student found = Student.GetStudents().Where(x => x.Id == id).FirstOrDefault();

            if (found != null)
            {
                EditStudent = new Student();
                EditStudent.Id = found.Id;
                EditStudent.Name = found.Name;
                EditStudent.Sex = found.Sex;
                EditStudent.Marks = found.Marks;
                return Page();
            }
            return Page();
        }

        public IActionResult OnPost()
        {
            string id = Request.Form["EditStudent.Id"];
            string name = Request.Form["EditStudent.Name"];
            string school = Request.Form["EditStudent.School"];
            string marks = Request.Form["EditStudent.Marks"];
            // update the list for the id
            
            return RedirectToPage("Index");
        }
    }
}

Run the application. We get the following form.

Click the Edit link. We get the following form. Input the data to update and click Submit button.


No comments:

Post a Comment

Hot Topics