ASP.NET Core is a cross-platform, high-performance, open-source framework for building modern, cloud-enabled, internet-connected apps.
The sitemap.xml file must be encoded with UTF-8. Example of sitemap:
<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>http://www.example.com/</loc> <lastmod>2005-01-01</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> <!-- ... --> </urlset>
As you can see, each URL in a sitemap contains four pieces of metadata:
<urlset>
and ends with </urlset>
always
, hourly
, daily
, weekly
, monthly
, yearly
, never
). This gives search engines an indication of how often they should come back and re-index the page.The last three values only give search engines an indication of when they can or should index or even re-index a page. It is not a guarantee that it will happen, although it makes it more likely.
A sitemap is a standalone page. On the razor page model, the ApplicationDbcontext is injected to work with the database.
Below code will generate XML string and return as ContentResult having ContentType = "application/xml".
Our page model code looks like as written below:
namespace Sample.Pages
{
public class SitemapModel : PageModel
{
public readonly ApplicationDbContext dbContext;
public SitemapModel(ApplicationDbContext dbContext)
{
this.dbContext = dbContext;
}
public IActionResult OnGet()
{
var pages = dbContext.Pages.ToList();
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version='1.0' encoding='UTF-8' ?><urlset xmlns = 'http://www.sitemaps.org/schemas/sitemap/0.9'>");
foreach (var page in pages)
{
string mDate = page.ModifiedDate.ToString("yyyy-MM-ddTHH:mm:sszzz");
var url = $"https://www.snippset.com/{page.Title}";
sb.Append("<url><loc>" + url + "</loc><lastmod>" + mDate + "</lastmod><changefreq>{page.Frequency}</changefreq><priority>{page.Priority}</priority></url>");
}
sb.Append("</urlset>");
return new ContentResult
{
ContentType = "application/xml",
Content = sb.ToString(),
StatusCode = 200
};
}
}
}
ASP.NET Core provides the option to set a friendly URL. So instead of just sitemap, it can be set to sitemap.xml.
By using AddPageRoute the route to a page can be configured with a friendly URL.
options.Conventions.AddPageRoute("/Sitemap", "Sitemap.xml");
Further information for sitemap.xml
This snipp explains how to configure Response Caching Middleware in an ASP.NET Core app.
In Startup.ConfigureServices
, add the Response Caching Middleware to the service collection using services.AddResponseCaching()
:
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCaching();
services.AddRazorPages(options =>
...
}
Configure the app to use the middleware with the UseResponseCaching extension method, which adds the middleware to the request processing pipeline in Startup.Configure
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseResponseCaching();
app.UseEndpoints(endpoints =>
...
}
In a controller action, add the [ResponseCache] attribute. The response cache middleware only works if the response cache attribute is added to the action method or controller.
[ResponseCache(Duration = 300)]
public class ImagesController : Controller
{
...
The following is a Response Header. It shows the cache-control:public and max-age=300
Response Header
cache-control: public,max-age=300
status: 200
...
x-powered-by: ASP.NET
Resources for Response Caching in ASP.NET Core
To inject configuration settings in your ASP.NET Core application, use Microsoft.Extensions.Configuration
and inject IConfiguration
into your page or component. Access configuration values using Configuration["KeyName"]
.
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
<!-- Access configuration value -->
@Configuration["ApplicationInsights:InstrumentationKey"]
For more structured configuration management, use the options pattern with Microsoft.Extensions.Options
. Inject IOptionsMonitor<TOptions>
with @inject
and access configuration values through OptionsAccessor.Value.PropertyName
.
@using Microsoft.Extensions.Options
@inject IOptionsMonitor<ApplicationInsightsOptions> ApplicationInsightsOptionsAccessor
<!-- Access configuration value -->
var instrumentationKey = ApplicationInsightsOptionsAccessor.Value.InstrumentationKey;
For detailed information, refer to the ASP.NET Core documentation on configuration options.
The following resources provide additional information.
The contents of a code block ({ ... }
) are expected to be code, not markup.
If you want to put text directly in a code block, you have three choices:
<text>
tag, which will just render the text without the tag@:
, which is equivalentUse the <text>
tags
The <text>
tag signals to the razor view engine to write the contents to the output.
@{ var foo = true; }
@if(foo) { <text>Yes</text> } else { <text>No</text> }
Use @:
Prefix the text with @:
before the first instance of text in the line. The parser is interpreting everything following @:Yes...
to be text.
@{ var foo = true;
if (foo)
{
@:Yes
}
else
{
@:No
}
}
Razor Syntax allows you to embed code (C#) into page views through the use of a few keywords (such as “@”), and then have the C# code be processed and converted at runtime to HTML. In other words, rather than coding static HTML syntax in the page view, a user can code in the view in C# and have the Razor engine convert the C# code into HTML at runtime, creating a dynamically generated HTML web page.
@page @model IndexModel <h2>Welcome</h2> <ul> @for (int i = 0; i < 3; i++) { <li>@i</li> } </ul>
Let’s say that you have class Person
and one of its properties is enum (in our case it’s enum Gender
).
public enum Gender { Unknown, Male, Female }
Below you can see Razor Page with a simple HTML form. Please remember to add the using statement to the folder where is defined your enum type (in my case it’s @using SelectBindingEnum.Models
).
<div class="form-group"> <label asp-for="Person.Gender" class="control-label"></label> <select asp-for="Person.Gender" asp-items="Html.GetEnumSelectList<Gender>()" class="form-control"></select> <span asp-validation-for="Person.Gender" class="text-danger"></span> </div>
As you can see above to binding enum values to HTML select tag you should use Tag Helper asp-items
and HtmlHelper method GetEnumSelectList<T>
where T
is an enum type. This method generates a SelectList object for all enum values. Also, this method allows you to add Display
attribute to your enum to change display text.
public enum Gender { [Display(Name = "None")] Unknown, Male, Female }
If you would add this attribute, you will see the following values in HTML select tag: None, Male and Female.
Some properties of model classes come as enums and we want to show Enum values in a select list. Sometimes we want enum element names but sometimes we want to use custom names or even translations.
Let’s define the enum and make it use DisplayAttribute and resource file.
public enum CustomerTypeEnum { [Display(Name = "Companies")] PrivateSector, [Display(Name = "PublicSector", ResourceType = typeof(Resources.Common))] PublicSector, Internal }
There are three different cases together now:
Important thing: set resource modifier to Public.
Now use the Html.GetEnumSelectList()
extension method to fill the select list with enum members. Notice the first empty selection (Select type …) as the only member of the select list.
<div class="form-group"> <label asp-for="Type" class="control-label"></label> <select asp-for="Type" class="form-control" asp-items="Html.GetEnumSelectList<CustomerTypeEnum>()"> option>Select type ...option> </select> <span asp-validation-for="Type" class="text-danger"><span> <div>
When we run the application we can see that the select list is filled with enum members and ASP.NET Core respects DisplayAttribute with static name and resource files.
If you don’t have control over enum (enum is defined in already built assembly) then you can’t apply Display attribute to enum and you need some other solution to get values you need.
ASP.NET Core has built-in Html.GetEnumSelectList()
method we can use to turn enum members to select list items. The method is intelligent enough to support the Display attribute and therefore we can use custom names for enum members and even translations from resource files.
Here’s my claims transformation that adds roles to user identity.
public class AddRolesClaimsTransformation : IClaimsTransformation
{
private readonly IUserService _userService;
public AddRolesClaimsTransformation(IUserService userService)
{
_userService = userService;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
// Clone current identity
var clone = principal.Clone();
var newIdentity = (ClaimsIdentity)clone.Identity;
// Support AD and local accounts
var nameId = principal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier ||
c.Type == ClaimTypes.Name);
if (nameId == null)
{
return principal;
}
// Get user from database
var user = await _userService.GetByUserName(nameId.Value);
if (user == null)
{
return principal;
}
// Add role claims to cloned identity
foreach(var role in user.Roles)
{
var claim = new Claim(newIdentity.RoleClaimType, role.Name);
newIdentity.AddClaim(claim);
}
return clone;
}
}
Open a new command prompt window and navigate to the folder that has your C#project file (.csproj file). Before we install Webpack, let us first create a package.json file. The package.json file holds metadata information and is used to give information to npm about a project’s (module)dependencies. To create a “default” package.json file, type the “npm init” command:
npm init -y
The “-y” option uses default options.
If the command was successful, it should have created a package.json file with contents similar to this:
{
"name": "demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
To now install Webpack (which is also a “module”), type the following command:
npm install webpack -D
If the command ran successfully, it should have created a new folder named “node_modules” in your project folder and downloaded several modules into this folder (into various folders), of course including the Webpack package as well.
Instead of a run-time dependency, the “ — save-dev” option adds a “dev dependency” to the package.json file. This indicates that the Webpack package is only useful during development. That would make sense, as once we have created the “bundles” as we require, we would use them directly in production. The package.json file should look similar to this:
{ "name": "demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", }, "devDependencies": { "webpack": "^4.46.0", } }
Create the webpack.config.js file in the root folder with this code:
const path = require(‘path’); module.exports = { mode: ‘development’, entry: ‘./wwwroot/source/app.js’, output: { path: path.resolve(__dirname, ‘wwwroot/dist’), filename: ‘bundle.js’ } };
As you can see above, we are giving Webpack the entry point, which is our app.js file. As well as telling it where to output the bundled file.
Babel is a transpiler. The transpiler transforms ES6 code to use ES5 syntax that older browsers can understand. While Babel itself is very feature-rich and can be used independently, for our purposes, we can use the corresponding babel “loaders” to do the job.
Before we can use any loaders, we need first to install them. For our purpose, we will have to install the relevant babel loaders. Use the following command to install the babel loaders and the “presets”.
npm install "babel-loader" @babel/core @babel/preset-env --save-dev
If the command ran successfully, these loaders would be installed in the node_modules folder and the package.json would be modified.
Update webpack with Babel using the next code
module: { rules: [ { test: /\.js$/, exclude: /(node_modules)/, use: { loader: ‘babel-loader’, options: { presets: [‘@babel/preset-env’] } } } ] }
Install React:
npm install react react-dom --save-dev
Install the Babel preset to process React JSX code:
npm install @babel/preset-react --save-dev
Add the React preset to Babel. It will convert React (JSX) code to raw JavaScript:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react', '@babel/preset-env']
}
}
}
]
}
Signing up for reCAPTCHA can be done here: https://www.google.com/recaptcha/about/. Once signed up, you will be guided through creating a new site (reCAPTCHA v2).
In the following steps, we will need both a reCAPTCHA Site Key and Secret Key. Bot keys are found on the settings screen on the new site:
reCAPTCHA is added by including the JavaScript from Google somewhere. For ASP.NET Core add it to the Scripts
section:
@section Scripts { <script src="https://www.google.com/recaptcha/api.js" async defer></script> <partial name="_ValidationScriptsPartial" /> </script>
Next, you will need to tell reCAPTCHA where to put the CAPTCHA control. Paste the following markup inside the form
element:
<div class="form-group"> <div class="g-recaptcha" data-sitekey="SITE_KEY"></div> </div>
For the data-sitekey
attribute, use the reCAPTCHA site key from the site settings.
The following sample will return JSON with a 200 OK status code (it's an Ok type of ObjectResult)
public IActionResult GetAsJson() { return new OkObjectResult(new Catagory { Id = 1234, Name = "Articles" }); }
The following code uses the Produces() attribute (which is a ResultFilter) with contentType = application/json
[Produces("application/json")] public Student GetWithProduces() { return new Catagory { Id = 1234, Name = "Articles" }; }
Return JSON with a 400 error code with a message
public IActionResult ErrorJSON() { return new JsonResult(new { message = "The Error Messages" }) { StatusCode = StatusCodes.Status400BadRequest // Status code here }; }
How to return JSON in camelCase?
Configure in Startup.cs
First of all, add this dependency:
using System.Text.Json;
Then add this in ConfigureServices():
services.AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; });
Change JsonSerializer options
Supply JsonSerializer.Serialize() with the optional JsonSerializerOptions object and override the casing:
string jsonString = JsonSerializer.Serialize(m, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
Razor Syntax allows you to embed code (C#) into page views through the use of a few keywords (such as “@”), and then have the C# code be processed and converted at runtime to HTML. In other words, rather than coding static HTML syntax in the page view, a user can code in the view in C# and have the Razor engine convert the C# code into HTML at runtime, creating a dynamically generated HTML web page.
@page @model IndexModel <h2>Welcome</h2> <ul> @for (int i = 0; i < 3; i++) { <li>@i</li> } </ul>
In a Razor view page (.cshtml), the @page
directive indicates that the file is a Razor Page.
In order for the page to be treated as a Razor Page, and have ASP.NET parse the view syntax with the Razor engine, the directive @page
should be added at the top of the file.
There can be empty space before the @page
directive, but there cannot be any other characters, even an empty code block.
@page @model IndexModel <h1>Welcome to my Razor Page</h1> <p>Title: @Model.Title</p>
The page model class, i.e. the data and methods that hold the functionality associated with a view page, is made available to the view page via the @model
directive.
By specifying the model in the view page, Razor exposes a Model
property for accessing the model passed to the view page. We can then access properties and functions from that model by using the keyword Model
or render its property values on the browser by prefixing the property names with @Model
, e.g. @Model.PropertyName
.
@page @model PersonModel // Rendering the value of FirstName in PersonModel <p>@Model.FirstName</p> <ul> // Accessing the value of FavoriteFoods in PersonModel @foreach (var food in Model.FavoriteFoods) { <li>@food</li> } </ul>
Razor pages use the @
symbol to transition from HTML to C#. C# expressions are evaluated and then rendered in the HTML output. You can use Razor syntax under the following conditions:
@
is assumed to be C# code.@{ ... }
brackets.( )
.@page @model PersonModel // Using the `@` symbol: <h1>My name is @Model.FirstName and I am @Model.Age years old </h1> // Using a code block: @{ var greet = "Hey threre!"; var name = "John"; <h1>@greet I'm @name!</h1> } // Using parentheses: <p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>
In Razor Pages, you can use the ViewData
property to pass data from a Page Model to its corresponding view page, as well as share it with the layout, and any partial views.
ViewData
is a dictionary that can contain key-value pairs where each key must be a string. The values can be accessed in the view page using the @
symbol.
A huge benefit of using ViewData
comes when working with layout pages. We can easily pass information from each individual view page such as the title
, into the layout by storing it in the ViewData
dictionary in a view page:
@{ ViewData["Title"] = "Homepage" }
We can then access it in the layout like so: ViewData["Title"]
. This way, we don’t need to hardcode certain information on each individual view page.
// Page Model: Index.cshtml.cs public class IndexModel : PageModel { public void OnGet() { ViewData["Message"] = "Welcome to my page!"; ViewData["Date"] = DateTime.Now(); } } // View Page: Index.cshtml @page @model IndexModel <h1>@ViewData["Message"]</h1> <h2>Today is: @ViewData["Date"]</h2>
Additional information ASP.NET Core Performance Best Practices | Microsoft Docs
Razor is a concise markup language that integrates server-side code (C# or VB) into ASP.NET web pages seamlessly. It simplifies web development by blending code and HTML, enhancing productivity and maintainability.
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<h1>@ViewData["Title"]</h1>
<p>Welcome to my ASP.NET Core Razor Pages!</p>
In this code snippet, the @page directive specifies the page, @model defines the page's model, and @ViewData displays dynamic data within the Razor Page markup.
Resources
Razor Syntax allows you to embed code (C#) into page views through the use of a few keywords, and then have the C# code be processed and converted at runtime to HTML.
Before jumping to the solution, let's talk about use cases. Using both tokens and cookies is not a common use case, but it typically comes up when you have a SPA or pure API applications that also need to secure some non-SPA pure Web Browser end points that the server sends directly to the browser. If that content needs to be protected behind authentication you might need Cookie authentication, because you can't do Bearer Token authentication with plain HTML interfaces in the browser.
services.AddAuthentication(options =>
{
// custom scheme defined in .AddPolicyScheme() below
options.DefaultScheme = "JWT_OR_COOKIE";
options.DefaultChallengeScheme = "JWT_OR_COOKIE";
})
.AddCookie("Cookies", options =>
{
options.LoginPath = "/login";
options.ExpireTimeSpan = TimeSpan.FromDays(1);
})
.AddJwtBearer("Bearer", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = config.JwtToken.Issuer,
ValidateAudience = true,
ValidAudience = config.JwtToken.Audience,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.JwtToken.SigningKey))
};
})
Source: Combining Bearer Token and Cookie Authentication in ASP.NET - Rick Strahl's Web Log (west-wind.com)
Here are six different ways to run your ASP.NET Core web application:
For more detailed information, check out the guide on 6 different ways to run an asp.net core web application (secretGeek.net)
Kubernetes ist in der Cloud-Welt allgegenwärtig; nahezu alle Public-Cloud-Anbieter offerieren Kubernetes als Managed Service oder nutzen es intern für ihre PaaS- und Serverless-Dienste. Auch in lokalen Rechenzentren wird Kubernetes häufig eingesetzt und entfaltet dort seine Stärken als Plattform. Obwohl sich die verschiedenen Kubernetes-Distributionen und Managed Services in technischen Details wie Installation und Integration von Netzwerk- und Speicherressourcen unterscheiden, bleibt die Plattform für Anwendungen weitgehend einheitlich. Mit minimalen Konfigurationsanpassungen können Applikationen sowohl in der Cloud als auch in On-Premises-Umgebungen nahtlos betrieben werden.
The following resources provide information for the Cache Tag Helper in ASP.NET Core
The following Razor markup caches the current date:
<cache>@DateTime.Now</cache>
The first request to the page that contains the Tag Helper displays the current date. Additional requests show the cached value until the cache expires (default 20 minutes) or until the cached date is evicted from the cache.
enabled
- Used to specify if this tag is enabled or notexpires-after
- Specifies the period of time after which the cached item should expireexpires-on
- Specifies the time at which the cached entry should expireexpires-sliding
- The period of time after the last access that the item should expirepriority
- Specifies the CacheItemPriority value of the cached itemvary-by
- Used to specify the parameters that determine whether different versions of the same content should be cachedThe Cache Tag Helper provides the ability to improve the performance of your ASP.NET Core app by caching its content to the internal ASP.NET Core cache provider.
The cache tag helper enables you to cache regions of a Razor page in memory on the server. Typical uses for this helper are for View Components or partial views that require relatively expensive database or web service calls, but where the content doesn't change very often. This type of caching its primarily used to improve a website's performance.
Unlike most other tag helpers, the Cache tag helper doesn't target a standard HTML element. It targets the <cache> tag, which is not rendered to the browser and doesn't appear in the HTML source either.
A sitemap is an XML file that contains all URLs of a website. When a website creates dynamic web pages, it is very difficult for Search Engines to search all URLs and index them. That is why we created a sitemap XML file and include all required URLs in it. It helps search engines find URLs easily and index them quickly.
The default URL is https://example.com/sitemap.xml