Saving the response cache to the server in Net 5 - caching

As in Net MVC, I want to save the response cache to the server (it's called outputcache), but there is no such feature in Net Core or Net 5. I couldn't find an alternative method. Thank you in advance.

You can use WebEssentials.AspNetCore.OutputCaching nuget to achieve your requirement.
Follow the steps below:
1.Add the middleware:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddOutputCaching();
//other middleware...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseOutputCaching();
//other middleware...
}
}
2.Add OutputCache attribute to the action:
[OutputCache(Duration = 600)]
public IActionResult Index()
{ ... }
A sample code for testing:
Controller:
[OutputCache(Duration = 600)]
public IActionResult Index()
{
return View(DateTime.Now);
}
View:
#model DateTime
Time of request: #Model.ToString()
Try requesting the page and notice that the date and time remains the same, even when reloading the page, until the cache has expired.
OutputCache contains not least Duration option, but also other options, such as VaryByHeader, VaryByParam and so on...
More details you can refer to the github repo for WebEssentials.AspNetCore.OutputCaching

Related

asp.net core web api work on iis express but not working in iis on windows

i am new in asp.net core. i use asp.net core 2.1. i have two controller. a default valuecontroller that doesn't have db connection and customerController that have sqlserver db connection. when i run my project on iis express everything is good but when i publish my project and use windows iis value api work nice but my customer api that have a sqlserver connection doesn't work.
appsettings calss:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Data Source=AHAD;Initial Catalog=mydb;Integrated Security=True"
}
}
Startup class:
namespace SalesApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddDbContext<MyDbContext>(Options =>
{
Options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
//,
//ILoggerFactory loggerFactory,
//MyDbContext db)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
//loggerFactory.AddConsole(Configuration.GetSection("Logging"));
//loggerFactory.AddDebug();
//db.Database.Migrate();
//app.UseMvc();
}
}
}
MyDbContext class:
public class MyDbContext : DbContext
{
public MyDbContext()
{
}
public MyDbContext(DbContextOptions<MyDbContext> options)
: base(options)
{
}
//public DbSet<CUSTOMER> customers { get; set; }
public DbSet<CUSTOMER> Customer { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CUSTOMER>(entity =>
{
entity.Property(e => e.C_Code).HasMaxLength(5);
entity.Property(e => e.C_Name).HasMaxLength(60);
entity.Property(e => e.C_Code_C).HasMaxLength(12);
});
}
}
CustomerController Class:
[Route("api/[controller]")]
[ApiController]
public class CustomerController : ControllerBase
{
MyDbContext _context;
public CustomerController(MyDbContext context)
{
_context = context;
}
[HttpGet]
public IActionResult GetCustomers()
{
return new ObjectResult(_context.Customer);
}
}
values api:
enter image description here
customer api:
enter image description here
it confused me 2 weeks.
You will need to have IIS set up in order to get it to work correctly.
You also need to ensure you are using the .NET Core Windows Server Hosting Bundle
Then:
Restart the system or execute net stop was /y, followed by net start w3svc from a command shell. Restarting IIS picks up a change to the system PATH, which is an environment variable, made by the installer.
After that open the command prompt as Administrator and type:
C:\Windows\System32> iisreset
Then publish the app to a folder and open the command prompt there. Run the application by typing
C:\Temp\publish> dotnet YourApplicationName.dll
You can now go to the browser and type in http://localhost:port/ and it will display your .Net Core app.
Using sql server auth worked for me.
I use connection string like this:
Server=.;
Database=myDB;
User Id=sa2;
Password=myPass;

How to bring in ASP.NET Core MVC to an existing ASP.NET blank project?

I have an ASP.NET Core blank project, and it works great to serve static files through https://localhost/filename. Now I want to add MVC functions to it. But referencing https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-controller?view=aspnetcore-2.2&tabs=visual-studio , after adding "Controllers" folder, add a controller class:
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/Welcome/
public string Welcome()
{
return "This is the Welcome action method...";
}
}
StartUp.cs is like:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
app.UseStaticFiles();
}
Builder is like:
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
after all this, I still can't access "https://localhost/HelloWorld/Welcome/".
What did I omit?
You have no default route specified, or routing of any sort for that matter. The quickest fix is to change app.UseMvc() to app.UseMvcWithDefaultRoute(). Alternatively, you can add attribute routes:
[Route("[controller]")]
public class HelloWorldController : Controller
{
[HttpGet("Welcome")]
public string Welcome()
{
return "This is the Welcome action method...";
}
}

ASP.Net Core:Claims Transformation and Authorization Policy

Please have a look at this url first https://weblogs.asp.net/imranbaloch/claims-transformation-and-authorization-policy-in-aspnet5-mvc6
public virtual Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
if (principal.Identity.IsAuthenticated)
{
// get this from cache or db
var country = "Pakistan";
(principal.Identity as ClaimsIdentity).AddClaim(new Claim("Nationality", country));
}
return Task.FromResult(principal);
}
when TransformAsync() will be called.......how to use it ?
[Authorize(Policy = "MustBePakistani")]
public IActionResult Message()
{
return Content("Hi Pakistani");
}
when Message action will be called then how asp.net mvc system will be able to understand what is user's nationality.....is it pakistani or indian ?
guide me how does it work. thanks
In addition to above two segments of the code in your question, you still need to add policy to authorization services in Startup.cs.
Example,
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthorization(options =>
{
options.AddPolicy("MustBePakistani", policy =>
policy.RequireClaim("Nationality", "Pakistan"));
});
services.AddSingleton<IClaimsTransformation, ClaimsTransformer>();
...
}
private class ClaimsTransformer : IClaimsTransformation
{
// Can consume services from DI as needed, including scoped DbContexts
public ClaimsTransformer(IHttpContextAccessor httpAccessor)
{
}
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
if (principal.Identity.IsAuthenticated)
{
// get this from cache or db
var country = "Pakistan";
(principal.Identity as ClaimsIdentity)
.AddClaim(new Claim("Nationality", country));
}
return Task.FromResult(principal);
}
}
}

Using FluentScheduler - ASP.NET Core MVC

I currently have a simple website setup with ASP.NET Core MVC (.NET 4.6.1), and I would like to periodically do some processes like automatically send emails at the end of every day to the registered members.
After doing some searching, I came across two common solutions - Quartz.NET and FluentScheduler.
Based on this SO thread, I found the approach of using FluentScheduler more easier to digest and use for my simple task. After quickly implementing the following lines of code into my Program.cs class, I had the emails going out successfully every minute (for testing purposes).
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
var registry = new Registry();
JobManager.Initialize(registry);
JobManager.AddJob(() => MyEmailService.SendEmail(), s => s
.ToRunEvery(1)
.Minutes());
host.Run();
}
}
However, now apart from sending emails I also need to do some back-end processing for e.g. updating the user records in the DB when mails are being sent out. For this, I normally inject my Entity Framework Context into the constructor of my controllers and use it to get/update SQL records.
My question is, since I cannot really inject these services into the main method, where would be the appropriate place to initialize the registry and add jobs for scheduling?
Thanks for the help, I am a little new to this so a little guidance would be much appreciated!
Instead of Program's Main function, I initialized the same in Startup.cs before app.UseMvc..
public void Configure(...., IDependencyObject dependencyObject)
{
....
JobManager.Initialize(new MyRegistry(dependencyObject));
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "api/{controller}/{action}/{id?}");
});
}
My registry class looks like this:
public class MyRegistry: Registry
{
public MyRegistry(IDependencyObject dependencyObject)
{
Schedule(() => new SyncUpJob(dependencyObject)).ToRunNow().AndEvery(10).Seconds();
}
}
My Job class looks like this:
public class SyncUpJob: IJob
{
public SyncUpJob(IDependencyObject dependencyObject)
{
DependencyObject= dependencyObject;
}
public IDependencyObject DependencyObject{ get; set; }
public void Execute()
{
// call the method to run weekly here
}
}
You can define all your jobs and their schedules, by subclassing from FluentScheduler Registry class. something like:
public class JobRegistry : Registry {
public JobRegistry() {
Schedule<EmailJob>().ToRunEvery(1).Days();
Schedule<SomeOtherJob>().ToRunEvery(1).Seconds();
}
}
public class EmailJob : IJob {
public DbContext Context { get; } // we need this dependency, right?!
public EmailJob(DbContext context) //constructor injection
{
Context = context;
}
public void Execute()
{
//Job implementation code: send emails to users and update database
}
}
For injecting dependencies into jobs, you need to implement FluentScheduler IJobFactory interface. GetJobIntance method is called by FluentScheduler for creating job instances. Here you can use any DI library you want; In this sample implementation, I'm going to assume that you use Ninject:
public class MyNinjectModule : NinjectModule {
public override void Load()
{
Bind<DbContext>().To<MyDbContextImplemenation>();
}
}
public class JobFactory : IJobFactory {
private IKernel Kernel { get; }
public JobFactory(IKernel kernel)
{
Kernel = kernel;
}
public IJob GetJobInstance<T>() where T : IJob
{
return Kernel.Get<T>();
}
}
Now you can start your jobs in main method by calling:
JobManager.JobFactory = new JobFactory(new StandardKernel(new MyNinjectModule()));
JobManager.Initialize(new JobRegistry());

Web Api with Sitecore 8.1

I've been trying to get Web Api to work with Sitecore 8.1.
I installed this package: https://www.nuget.org/packages/Krusen.Sitecore.WebApi.Custom/ and I modified the ConfigureWebApi to the following:
public class ConfigureWebApi
{
public void Process(PipelineArgs args)
{
GlobalConfiguration.Configure(config => config.Routes.MapHttpRoute("API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional }));
GlobalConfiguration.Configure(config => config.MapHttpAttributeRoutes());
GlobalConfiguration.Configure(ReplaceControllerSelector);
}
private static void ReplaceControllerSelector(HttpConfiguration config)
{
config.Services.Replace(typeof (IHttpControllerSelector),
new CustomHttpControllerSelector(config, new NamespaceQualifiedUniqueNameGenerator()));
}
}
However, whenever I use post requests, I get the following error:
{"Message":"The requested resource does not support http method
'POST'."}. Get requests work.
This is the implementation of the controller:
[RoutePrefix("api/authentication")]
public class AuthenticationController : ApiController
{
[Route("email")]
[HttpPost]
public bool Login([FromBody] string email)
{
return true;
}
}
I figured out what the error was. When my controller was called AuthenticationController it gave the following error:
The requested document was not found
If I called it something else, the web api worked as a charm e.g.
public TestController : ApiController {
//Code goes here
}

Resources