I'm following this tutorial to setup Ids4, my steps were the same as the video but I'm getting a 404 when I navigate to https://localhost:5443/.well-known/openid-configuration.
Things I did :
created a new Web APP
-added the IdentityServer4 nuget package
-edited the startup as follows:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddInMemoryClients(new List<Client>())
.AddInMemoryIdentityResources(new List<IdentityResource>())
.AddInMemoryApiResources(new List<ApiResource>())
.AddInMemoryApiScopes(new List<ApiScope>())
.AddTestUsers(new List<TestUser>())
.AddDeveloperSigningCredential();
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseIdentityServer();
app.UseAuthentication();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());
}
}
}
If I navigate to localhost, it displays a hello world as it should, but the discovery document returns a 404. Any ideas as to why?
The order of your middlewares is incorrect. Here's how it should be
Also, to determine what's going wrong, you must check for errors in the Visual Studio Output window
Related
I have an API which contains a HostedService that is built in VS2022 with .Net 6.
When I run locally the service is called as expected and everything works fine but when deplyed, the service doesn't seem to start.
I have tried many different configurations and even tried using a background service but it all has the same result. Here is my code:
I have an existing app build in VS2019 .Net Core 3.1 that has a HostedService and is working fine. I noticed that when I converted my .Net Core app to .Net 6, the service did not start when I deployed so I decided to just build a little app to try and find what's causing the issue.
Program.cs
using HostedServices.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(context.Configuration)
.Enrich.FromLogContext()
.Enrich.WithMachineName());
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddHostedService<MainService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Here is the Hosted Service
namespace HostedServices.Services
{
public class MainService : IHostedService, IDisposable
{
private int executionCount = 0;
private readonly ILogger<MainService> _logger;
private Timer _timer;
private Task _executingTask;
private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();
public MainService(ILogger<MainService> logger)
{
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Test Hosted Service Started {DateTime.Now}.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromMinutes(1));
return Task.CompletedTask;
}
private void DoWork(object state)
{
_executingTask = DoWorkAsync(_stoppingCts.Token);
}
private async Task DoWorkAsync(CancellationToken token)
{
_logger.LogInformation(
"Doing work: {0}", DateTime.Now);
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Service is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}
Everything runs fine locally but when I deploy it, the service doesn't seem to start, no log files are generated and I can't seem to find any errors reported.
Any ideas?
We had the same problem and resolved it by following IIS settings:
Under "Page" Advanced Settings: "Preload Enabled" must be set to "true" (this forces app to run after every app pool recycle and on startup)
Under "App Pool" Advanced settings: "Start mode" must be set to "AlwaysRunning"
"Page" in IIS must have http allowed (since preload enabled works only on http and not via https)
The problem is that while IHostedService start when the site starts when does IIS start the site? By default, it doesn't until a request is made. If your site goes idle for a while IIS will kill the thread as well.
IIS has a feature you can enable called "Application Initialization".
You then need to configure the Application Pool to always start (startMode="AlwaysRunning").
Lastly, you configure the site's application to preload which sends a fake HTTP request to the site on startup (preloadEnabled="true").
The docs for this are here: https://learn.microsoft.com/en-us/iis/get-started/whats-new-in-iis-8/iis-80-application-initialization
I'm working on a project in ASP .NET Core 3.1 MVC now I want to add some API controllers to return list of objects.
For this I want to use OData Controller version 8.0.0 so I can get quarriable data to improve performance on large data tables
I'm new in ASP .NET Core and OData. can anybody explain how to configure my project's Startup file so I can run both MVC and OData controllers same time.
Kindly share some example code
Firstly, you have a MVC project, since MVC project can also expose API, so OData should also work for MVC project. Firstly, assuming you've integrate ef core and in my workaround, I followed this document to create database and data management view for a model.
Then let's add OData. Install this nuget package: Microsoft.AspNetCore.OData, modify your startup.cs file, please see the Configuration and GetEdmModel method.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using WebMvcNet5.Data;
using WebMvcNet5.Models;
using Microsoft.OData.ModelBuilder;
using Microsoft.AspNetCore.OData;
using Microsoft.OData.Edm;
namespace WebMvcNet5
{
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.AddControllersWithViews();
services.AddControllers().AddOData(opt => opt.EnableQueryFeatures().AddRouteComponents("odata", GetEdmModel()));
services.AddDbContext<WebMvcNet5Context>(options =>
options.UseSqlServer(Configuration.GetConnectionString("WebMvcNet5Context")));
}
// 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();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
//My model is Movie, and what I set "GetMovie" here means I need to create a controller named "GetMovieController"
builder.EntitySet<Movie>("GetMovie");
return builder.GetEdmModel();
}
}
}
Then this is my controller:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using WebMvcNet5.Data;
namespace WebMvcNet5.Controllers
{
[Route("odata/[Controller]")]
public class GetMovieController : Controller
{
private readonly WebMvcNet5Context _context;
public GetMovieController(WebMvcNet5Context context)
{
_context = context;
}
[EnableQuery]
public IActionResult Get()
{
return Ok(_context.Movie);
}
}
}
My test result:
I have managed to fix my issue to run Web Application which exposes OData APIs
Issue was in Startup.cs file
I'm using Asp.Net Core 3.1 and Microsoft.AspNetCore.OData v7.3.0
my Startup.cs file code is:
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.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<AppUser, AppRole>(opt =>
{
opt.User.RequireUniqueEmail = true;
})
//.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
//add services
services.RegisterServices();
services.AddScoped<ViewRendererService>();
services.AddMvc()
.AddMvcOptions(options => options.EnableEndpointRouting = false)
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddOData();
services.AddRouting();
services.AddControllersWithViews();
services.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApplicationDbContext dataContext)
{
if (env.EnvironmentName == "Development")
{
dataContext.Database.Migrate();
app.UseDeveloperExceptionPage();
}
else
{
app.UseDeveloperExceptionPage();
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseRequestLocalization();
app.UseMvc(routes =>
{
routes.Select().Filter().OrderBy().Expand().Count().SkipToken().MaxTop(null);
routes.MapODataServiceRoute("odata", "api", GetEdmModel());
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
routes.MapRoute(
name: "Finance",
template: "{area:exists}/{controller=Account}/{action=Index}/{id?}"
);
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("ProductApi");
builder.EntitySet<ProductUOM>("ProductUomApi");
ActionConfiguration action = builder.EntityType<Product>().Action("GetUOM");
action.Parameter<long>("id");
action.ReturnsCollectionFromEntitySet<Product>("Product");
return builder.GetEdmModel();
}
}
Hope this will help others
I'm currently trying to mount a .NET Core 3.1 MVC application created with dotnet new react. The application works perfectly fine when running it via Visual Studio Code. However, when publishing with dotnet publish -c Release -r win81-x64 and mounting the application in IIS 8.5, the routes for the APIs stop working, sending all requests to the React page.
Currently my configuration in Startup.cs looks like this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
And the code in a test controller I made looks like this:
namespace Application.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase {
private readonly ILogger<TestController> _logger;
public TestController(ILogger<TestController> logger)
{
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<string>> GetTest()
{
return "Test";
}
}
}
I also tried creating a new React project and mounting it, and that does seem to work. However, the Startup.cs file has the exact same configuration, so I can't find anything to modify on my application.
I figured it out. Turns out the first version I uploaded had some issues that prevented routes from working properly, and while I immediately fixed it, the Service Worker that the default .NET project has cached the broken API point as part of the site. Apparently this bypasses having the 'Disable Cache' tick box in developer tools.
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...";
}
}
With .NET 4.6.1 I wanna use Sessionstate in a class library, something like :
public static void SetUserId()
{
HttpContext.Current.Session["userId"] = 1;
}
but when I call this method it throws an exception "An unhandled exception occurred while processing the request." > "NullReferenceException: Object reference not set to an instance of an object."
I have a reference to system.Web in my class library. In .NET 4 I can do this safe. But it is a problem in .NET 4.6.1.
How can I solve this?
Thanks
This is null by default, the concept driving ASP.NET Core 1.0 is pluggable middleware. You need to explicitly opt-in for session.
You need to ensure that both the Microsoft.Extensions.Caching.Memory and Microsoft.AspNet.Session dependencies exists in the project.json. Then in your
Startup.cs add the following:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddCaching();
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.CookieName = ".MyApplication";
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSession();
// Removed for brevity...
}
Detailed article here. That should be all you need to do.
Update
Avoid attempting to use HttpContext.Current outside of the web application. This is intended only within the context of the HTTP request / response pipeline. It is preferred to utilize abstractions to achieve the desired interactions you're looking for.
I would need you to share more source code in order to provide an explicit example.