What is the alternative for context.Response.SetValidUntilExpires(true) in asp.net core?
I checked the headers in an asp.net app, and could not find any changes on setting the flag as true or false.
context.Response.Cache.SetExpires(DateTime.Now.AddDays(7));
context.Response.Cache.SetValidUntilExpires(true);
context.Response.Cache.SetCacheability(HttpCacheability.Public);
Whenever you want to cache something, do not trust the client. The client can easily ignore it and ask your API again and again.
A better approach would be to use server side caching techniques.
However, it is possible to use the ResponseCacheAttribute to solve your issue. Here is an example.
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
[ResponseCache(Duration = 123, VaryByHeader = "User-Agent")]
public IEnumerable<string> Get()
{
return new string[] {"value1", "value2"};
}
}
}
In case you are serving static files. Caching is achieved by configuring it in the Startup.cs File of your project.
Here is an example:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.Net.Http.Headers; // required
namespace WebApplication1
{
public class Startup
{
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var durationInSeconds = (int) TimeSpan.FromDays(1).TotalSeconds;
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = context =>
{
context.Context.Response.Headers[HeaderNames.CacheControl] =
$"public,max-age={durationInSeconds}";
}
});
app.UseMvc();
}
}
}
Related
I am newby in .NET, I know more about BE development in Vapor. Anyway.
How can I find the available routes in a .NET app?
How can I know which parameters are accepted.
Thia app here does a transformation from DB to XML stored in an FTP, back and forth. Basically only signals are sent to the app, but I do not know how.
This is the file structure:
And I found some "route-like" lines here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ptoolApi.Models.IFS;
using ptoolApi.Services;
namespace ptoolApi
{
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.AddControllers();
services.AddDbContext<ifsContext>(opts => opts.UseSqlServer(Configuration["ConnectionString:IFS"]));
services.AddScoped<ISqliteService, SqliteService>();
services.AddSwaggerGen(swagger =>
{
swagger.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
{
Title = "pTool API",
Version = "v2.1.5",
Description = "Tool to convert PFB plist file to a sqlite DB, and vice versa"
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSwagger();
app.UseSwaggerUI(c =>
{
#if DEBUG
c.SwaggerEndpoint("/swagger/v1/swagger.json", "pTool API");
#elif DEVELOPMENT
c.SwaggerEndpoint("/dev/ptooldb/swagger/v1/swagger.json", "pTool API");
#elif STAGE
c.SwaggerEndpoint("/stage/ptooldb/swagger/v1/swagger.json", "pTool API");
#elif RELEASE
c.SwaggerEndpoint("/ptooldb/swagger/v1/swagger.json", "pTool API");
#endif
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Is here /swagger/v1/swagger.json a route? And what is the accepted arguments?
Meantime I tried
http://localhost:50491/swagger
http://localhost:50491/swagger/index.html
send POST with this parameter
{
"xmltodb": false,
"dbtoxml": true,
"airlineID": 2901,
"deploy": false,
"XamarinMigration": false,
"environment": "prod"
}
But all is refused, though I found these line under controller:
[HttpGet]
public RedirectResult Get()
{
return RedirectPermanent("/swagger/index.html");
}
[HttpPost]
public async Task<ActionResult> Post(PToolInput input)
{
try
{
Globals.WriteToLog("Start the connection");
The "Routes" are in the Controllers folder. There are classes called Controllers there which have methods, that can represent an action (a url). Swagger is a tool to scaffold the api and create a OpenApi documentation for it.
Swagger is a tool (language?) used to describe/document APIs. I think all .NET/.NET Core APIs by default include this tool as part of Swashbuckle.
If you debug the API, and navigate to the /swagger endpoint, it should display you the Swagger documentation of your API. Which I think in turn, will satisfy what you are looking for - the routes (endpoints) of the API and what parameters they take, etc. These are your Controller methods essentially, which can be found in your Controllers folder.
An example of a basic controller method may look like:
[ApiController]
[Route("test")]
public class TestController : Controller
{
[HttpGet]
public List<MyTestModel> Get()
{
List<MyTestModel> models = new List<MyTestModel>
{
new MyTestModel
{
SomeString = "Hello world!",
SomeInteger = 101,
SomeBool = true
}
};
return models;
}
}
Notice how the class is decorated with the Route attribute. This defines the route for all the controller methods found in the controller. In this particular example, the route (or URI really) would be https://<root>/test/. Performing a GET against this resource would yield the following JSON:
[
{
"someString": "Hello world!",
"someInteger": 101,
"someBool": true
}
]
Alternatively, you can have another method with the decorator of [HttpPost], and performing a POST against the same URI would execute said method.
For more information, see the Microsoft documentation on routing in ASP.Net Core - it's very detailed!
I see an official video of visual studio show how to do this. But in the end, the instructor can't make it work, he must alter UseSqlServer() with UseInMemoryDatabase() in Startup.cs.
Here is my code, i follow his instruction.
Firstly, create a file with classes that one contain Dbcontext, others map with tables in database. In my case, database just have one table: Students. This is class contain Dbcontext:
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace HoangHoaTham.WebAPI.Entities
{
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options) : base(options)
{
}
public DbSet<Students> Students;
}
}
My Startup.cs, i add UseSqlServer here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HoangHoaTham.WebAPI.Entities;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace HoangHoaTham
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(options
=> options.UseSqlServer(Configuration.GetConnectionString("HoangHoaTham")));
services.AddMvc();
}
//You don't need to reed the code below
// 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();
}
}
}
Finally, I add ConnectionString into appsetting.json:
{
"ConnectionString": {
"HoangHoaTham": "Server=PC-PC\\SQLEXPRESS;Database=HoangHoaThamHighSchool;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Anh it doesn't work. The error :
enter image description here
Here is his video: https://www.youtube.com/watch?v=aIkpVzqLuhA
Skip to 50:47 to see how he did that.
Thank you so much.
The error is telling you that the result of Configuration.GetConnectionString("HoangHoaTham") is null. Therefore, there's some issue with your configuration, and it turns out there is: the connection string section in appsettings.json is supposed to be ConnectionStrings (plural). You've got ConnectionString (singular) instead.
The error is for the ConnectionString you used in appsetting.json just try this code in your appsetting.json1 and tweak the connectionstring` as per your requirements this would work.
ASP.NET Core Web API
{
"ApplicationInsights":{
"InstrumentationKey":""
},
"ConnectionStrings":{
"DefaultConnection":"Server=srvrName;Database=Test;User Id=User;Password=pass"
},
"Logging":{
"LogLevel":{
"Default":"Warning"
}
},
"AllowedHosts":"*"
}
I am in MVC Core application. I added System.Web to my using clause but still I cannot access httpcontext.Session. The intellisense does not give me any option for httpcontext. Thanks for your answer.
Edit:
I have found this answer: https://benjii.me/2016/07/using-sessions-and-httpcontext-in-aspnetcore-and-mvc-core/
But when I add the nuget package: Microsoft.AspNetCore.Session into my project the solution won't even load anymore. So I had to remove it
Edit: Now I have added the most recent version of the package from nuget console. But I still do not have HttpContext option in the intellisense so I cannot access the session. Please help..
In System.Web I have only the following object: HttpUtility and nothing more,
is there anyone that can help? Without Sessions I cannot write any applications. Should I reinstall Visual Studio?
Notice**: In my webforms application I have the object Session in system.web
As required I post my Startup.cs and the file in which I am trying to call the object Session:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Localization;
using WebCoreFly.Models;
namespace WebCoreFly
{
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();
services.AddDbContext<FlyDBContext>(options =>
options.UseSqlServer(Configuration["Data:WebCoreFly:ConnectionString"]));
services.AddSingleton<FlyRepository>();
}
// 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.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
the class in whic I am trying to call session:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace WebCoreFly.Models.ViewModels
{
public class UserRepository1
{
public UserRepository1()
{
System.Web.HttpContext //does not recognize it
}
}
}
So I just ran across this very odd issue building a simple WebAPI template using .NET Core (2.1.200 cli) and VSCode (1.23.1). Most exceptions, if thrown, put me into the VSCode debugger and upon continuing return a Developer Exception page sent to the browser. However when a ArugmentNullException is thrown... hard crashes the application with no VSCode debugger interaction.
Program.cs (default webapi template code)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace ExceptionIssue {
public class Program {
public static void Main(string[] args) {
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
Startup.cs (default webapi template code)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace ExceptionIssue {
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();
}
// 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();
}
}
}
.\Controllers\ValuesController.cs (modified get)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace ExceptionIssue.Controllers {
[Route("api/[controller]")]
public class ValuesController : Controller {
// GET api/values
[HttpGet]
public IEnumerable<string> Get() {
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id) {
String result = null;
switch (id) {
case 1:
throw new Exception("One");
break;
case 2:
throw new ArgumentNullException("Two");
break;
case 3:
result = String.Format(null, "UH OH");
break;
case 4:
String template = null;
result = String.Format(template, "UH OH");
break;
}
return result;
}
// POST api/values
[HttpPost]
public void Post([FromBody]string value) {
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value) {
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id) {
}
}
}
Also note that String.Format(null, "UH OH"); returns "UH OH" whereas String.Format(template, "UH OH); throws a ArgumentNullException (not sure why there is a difference, shouldn't they both do the same thing).
Not sure if this is a .NET Core, Kestrel, or VSCode issue, but it's 100% reproducible on my part.
I had a couple co-developers helping me dig deep on this, and it looks like this is actually an issue with the ms-vscode.chsarp (1.15.1) debugger itself.
Running my code without debugging (CTRL-F5) works as expected. Likewise running my code with debugging on an older version of the debugger also works as expected. So this appears to be bug in the latest version of the debugger, which makes sense since the app just hard crashes without even breaking on the line that threw the exception.
Guess I'll bring this to the guys over at Omnisharp.
I am building an ASP.NET Core API (1.1) in Visual Studio Code using Windows Impersonation for authentication. (The API allows researchers to create Samples.) I am using this impersonation middleware to handle authentication, which passes on the user identity nicely when connecting to the underlying SQL Server database.
However, for some write actions, I would like to add the name of the user who created the object as a value to the database (i.e. the name of the researcher creating the sample). I can't seem to make it work. I based my solution on the responses to these questions: How to get the current logged in user Id ASP.NET Core and ASP.NET Core Identity does not inject UserManager<ApplicationUser> and this tutorial, even though they seem to be aimed at storing the user identities in separate tables in the SQL server database, which is not my intent. I only need the username of the user sending the request.
I get the following error message on the line var user = await GetCurrentUserAsync(); in my controller.
The 'await' operator can only be used within an async method.
Consider marking this method with the 'async' modifier
and changing its return type to 'Task<IActionResult>'
My question is twofold:
How can I fix this error?
Is there an easier/better way to get the User Identity in my situation.
My Controller file
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;
using MyAPI.Model;
using MyAPI.Services;
namespace MyAPI.Controllers
{
[Route("api/[controller]")]
public class SamplesController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);
[HttpPost]
public IActionResult Post([FromBody] Sample sample)
{
var user = await GetCurrentUserAsync();
var userId = user?.Id;
// I abstracted the underlying logic of creating a sample in the database
//because it is quite complex and doesn't seem relevant to this problem
CreateSample(sample, userId);
}
}
}
Startup.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using MyAPI.Model;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Impersonate.AspNetCore.Windows;
namespace MyAPI
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add framework 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, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseWindowsImpersonation(options => { options.Enabled = true; });
app.UseMvc();
}
}
}
MyAPI.Model.ApplicationDbContext file
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
namespace TrinityAPI.Model
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
{
Database.EnsureCreated();
}
}
}
MyAPI.Model.ApplicationUser file
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
namespace TrinityAPI.Model
{
public class ApplicationUser : IdentityUser
{
}
}
With Windows authentication enabled and inside the code for a controller action, you can find out information about the current user by going to the User object on the HttpContext property. For example, the following action should show domain\username for the current user.
public IActionResult Index()
{
return Content(HttpContext.User.Identity.Name);
}
When using Windows authentication, your are correct in thinking that you don't want to use ASP.NET Identity. You can remove the ApplicationDbContext class as well as the AddIdentity call in your Startup class.