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

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;

Related

OData Controller withing Asp.Net Core MVC application

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

Saving the response cache to the server in Net 5

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

BackgroundService with asp.net Core MVC 3.1

Here is what i've done:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddHostedService<MyBatch>();
}
public class MyBatch : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!stopToken.IsCancellationRequested)
{
Console.Writeline("test");
await Task.Delay(TimeSpan.FromSeconds(10));
}
}
}
I have 2 problems:
First: The web application does not respond on 5000 port when i launch "dotnet run". If i remove my batch, the 5000 port works again. (test messages are displayed on console)
Second: I want to access to my database with Entity Framework. How can i access to my database context from this batch file ?
Thanks
I want to access to my database with Entity Framework. How can i access to my database context from this batch file ?
To consume a scoped service (such as DbContext etc) from singleton hosted service, you can create a scope then use it to resolve scoped service(s) you need from this scope, like below.
public class MyBatch : BackgroundService
{
public IServiceProvider Services { get; }
public MyBatch(IServiceProvider services)
{
Services = services;
}
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!stopToken.IsCancellationRequested)
{
Console.WriteLine("test");
await Task.Delay(TimeSpan.FromSeconds(10));
await DoWithDb(stopToken);
}
}
private async Task DoWithDb(CancellationToken stoppingToken)
{
//...
using (var scope = Services.CreateScope())
{
var _myDbContext =
scope.ServiceProvider
.GetRequiredService<MyDbContext>();
//code logic here
//...
}
}
}
You can also get detailed information about "consuming a scoped service in a background task" from here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio#consuming-a-scoped-service-in-a-background-task

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...";
}
}

Adding custom authorize claim based on local database for Azure user .net core

I am trying to recognize database user with Azure AD email address, and then add custom claim to azure AD authenticated user, based on property from local database user. In startup.cs I got:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IClaimsTransformer, ClaimsTransformer>();
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, KayttajatContext context)
{
...
app.UseClaimsTransformation(async (c) =>
{
IClaimsTransformer transformer = c.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return await transformer.TransformAsync(c);
});
...
}
Then ClaimsTransformer.cs looks like this:
namespace Authtest
{
public class ClaimsTransformer : IClaimsTransformer
{
private readonly KayttajatContext _context;
public ClaimsTransformer(KayttajatContext dbContext)
{
_context = dbContext;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext ctrans)
{
string sposti = ((ClaimsIdentity)ctrans.Principal.Identity).Name;
var user = await _context.Henkilöt.FirstOrDefaultAsync(t => t.Sposti == sposti);
if (user.Sposti == sposti)
{
((ClaimsIdentity)ctrans.Principal.Identity).AddClaim(new Claim(ClaimTypes.Role, "Administrator"));
((ClaimsIdentity)ctrans.Principal.Identity).AddClaim(new Claim(ClaimTypes.Role, "User"));
}
else
{
((ClaimsIdentity)ctrans.Principal.Identity).AddClaim(new Claim(ClaimTypes.Role, "User"));
}
return ctrans.Principal;
}
}
}
But this gives me "NullReferenceException: Object reference not set to an instance of an object." at if (user.Sposti == sposti)
If I instead give string value to either one of the variables, if statement works fine. I don't know what I'm doing wrong? Does it have something to do with async? Please help this is driving me nuts.
I was trying to call string sposti = ((ClaimsIdentity)ctrans.Principal.Identity).Name; before it was set. Works now, thanks :)

Resources