ASP.NET Core MVC - Connection strings and Data Libraries - asp.net-core-mvc

I'll prefix this and say I'm new to .net core. I've been taken by surprise when trying to access a connection string I have in my appsettings.json file.
My solution has 2 projects, an MVC project and a Data Library. In the past with standard .net I was able to add a connection string into my web.config and access it from my data library like so:
namespace DataLibrary.DataAccess
{
public static class SqlDataAccess
{
public static string GetConnectionString(string myConnection = "DemoDB")
{
return ConfigurationManager.ConnectionStrings[myConnection].Connectionstring;
}
}
}
The "DemoDB" is the name of the connection string in the web.config. This doesn't work with .net core. I was wondering if someone could get me a step by step, talk to me like I'm 5, explanation of how I would get the connection string from my appsettings.json file in my MVC project into my DataLibrary?
Thanks in advance!

As far as I know, if you want to use data library in the MVC project, you should register it as a service in the main project.
More details, you could refer to below codes:
public static class ServiceCollectionExtensions
{
public static IServiceCollection RegisterDataService(this IServiceCollection serviceDescriptors,IConfiguration configure) {
serviceDescriptors.AddDbContext<TestDBContext>(o => o.UseSqlServer(configure.GetConnectionString("ConnectionStringanme")));
return serviceDescriptors;
}
}
Then in the main MVC project's startup.cs method, you could use below codes:
services.RegisterDataServices(Configuration)
At last, you could add connection string into appsettings.json as below:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-ASPNETCoreIdentity-AE5A1558-8D92-4DA4-9A53-DDFB0BA30404;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
More details, you could refer to this article.

Related

How to read Appsettings.Json in .net 6 Web API with F#

I want to read a simple connection string from the appsettings.json file in F#
"ConnectionStrings": {
"myConnectionString": "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"
}
In C# I could use the read the connection string with an object from a class implementing the Iconfiguration provided in the constructor. But in the F# web API with .net 6, I couldn't find anything that made me read the connection string section or an other key in from the AppSettings.json file
Here is an example how I could read from the Appsettings.json in C# .net 6 Web API. This is what I want to do.
public class TestModel : PageModel
{
// requires using Microsoft.Extensions.Configuration;
private readonly IConfiguration _configuration;
public TestModel(IConfiguration configuration)
{
_configuration = configuration;
}
public void Connect()
{
var connectionString = _config.GetConnectionString("myConnectionString");
// Do Something with the string
}
}
The F# implementation of the Web API project is very similar to the C# one. In order to use the configuration in one of your classes you just need to inject the IConfiguration parameter to the constructor of your class. The default bootstrap code takes care of setting up the dependency injection for the configuration framework.
I created a sample Web API project for F# and injected the IConfiguration to the controller:
namespace WebApiTest.Controllers
open System
open System.Collections.Generic
open System.Linq
open System.Threading.Tasks
open Microsoft.AspNetCore.Mvc
open Microsoft.Extensions.Logging
open Microsoft.Extensions.Logging
open WebApiTest
open Microsoft.Extensions.Configuration
[<ApiController>]
[<Route("[controller]")>]
type WeatherForecastController (logger : ILogger<WeatherForecastController>, configuration: IConfiguration) =
inherit ControllerBase()
let summaries =
[|
"Freezing"
"Bracing"
"Chilly"
"Cool"
"Mild"
"Warm"
"Balmy"
"Hot"
"Sweltering"
"Scorching"
|]
[<HttpGet>]
member _.Get() =
let cstr = configuration.GetConnectionString("MyConnectionString")
logger.LogInformation($"Connection string: {cstr}")
let rng = System.Random()
[|
for index in 0..4 ->
{ Date = DateTime.Now.AddDays(float index)
TemperatureC = rng.Next(-20,55)
Summary = summaries.[rng.Next(summaries.Length)] }
|]
As you see, the configuration parameter injected in the constructor is accessible as a private member variable in the Get() method. I just log the connection string to illustrate that the code works as expected.
Here's my appsettings.json:
{
"ConnectionStrings": {
"MyConnectionString": "SampleConnectionString"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

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

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;

.net 5 MVC 6 web api using existing identityDb for authentication

I am working on having native app be able to authenticate to a web api which uses an existing identity db database created from MVC6. I understand this is not a secure way of doing things as per this post. However, until I can figure out how to get IdentityServer3 working with a database I thought I would try a simple web api that authenticates to a database I already created when I built a standard MVC 6 web app. Here is what I did:
Created an asp.net 5 web api from the template and added the following:
Settings:
appsettings.json I added:
"Data": {
"DefaultConnection": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-TestUsers-eaf0c85f-23e4-4603-97ce-b9f49ee1d167;Trusted_Connection=True;MultipleActiveResultSets=true"
}
},
Startup:
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<ApiDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
Models:
public class AppUser : IdentityUser
{
}
DBContext:
public class ApiDbContext : IdentityDbContext<AppUser>
{
}
Controller:
private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signInManager;
private readonly ILogger _logger;
...
public async Task<IEnumerable<string>> Post([FromBody]LoginModel model)
{
if (ModelState.IsValid) {
string user = model.userid;
string passwd = model.password;
var result = await _signInManager.PasswordSignInAsync(model.userid, model.password, false, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation(1, "User logged in.");
return new string[] { user };
}
else
{
return new string[] { "Failed" };
}
}
else
{
return new string[] { "Incorrect format received"};
}
}
However, it bombs at the _signInManager line with the error:
System.NullReferenceException: Object reference not set to an instance
of an object.
So apparently _signInManager is Null because I know the model is fine because I am printing the userid and password and they are there.
What am I missing so I can use the signInManager in a web api?
I went back yet another time to see what was different between the web api and the web app, since the web app auth was working fine. Here is what I added to get it working:
controller needed a constructor:
public AuthController(
SignInManager<AppUser> signInManager,
ILoggerFactory loggerFactory)
{
_signInManager = signInManager;
_logger = loggerFactory.CreateLogger<AuthController>();
}
Which got rid of my other error but produced the following error:
System.InvalidOperationException: No authentication handler is
configured to handle the scheme: Microsoft.AspNet.Identity.Application
So after researching that I needed to add to startup:
configureservices:
services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<ApiDbContext>()
.AddDefaultTokenProviders();
configure:
app.UseIdentity();
Adding these to the above allowed me to post JSON with userid and password.

Examples of how to use NServiceBus with NServiceBus.Ninject-CI in ASP.NET MVC 3 solution

I would like to experiment with NServiceBus using ASP.NET MVC 3. I've got a solution with NServiceBus installed, plus NinjectMVC3 and NServiceBus.Ninject-CI. Trouble is, I have no idea how to setup NServiceBus stuff in the NinjectMVC3.cs file in App_Start.
Rather annoyingly I'm having trouble finding any examples of how to use NServiceBus.Ninject-CI (I hate it when people don't bother giving examples of how to use their stuff).
Can someone help me get started please?
Load a module like this into the kernel to provide access to the bus
public class NServiceBusModule : NinjectModule
{
public override void Load()
{
this.Bind<IBus>().ToConstant(this.CreateBus()).InSingletonScope();
}
private IBus CreateBus()
{
return NServiceBus.Configure.WithWeb()
.NinjectBuilder(this.Kernel)
... // put NServiceBus config here
.CreateBus()
.Start();
}
}
Read the NServiceBus documentation about how to configure NServiveBus:
http://docs.particular.net/nservicebus/containers/ninject
http://docs.particular.net/samples/web/asp-mvc-application/
Hopefully this will help someone. I had a lot of trouble finding sample code for getting ninject working within NServiceBus.
This code below works for me in place of the more common Castle version:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
#region IWantCustomInitialization Members
public void Init()
{
Configure
.With()
.NinjectBuilder(CreateKernel())
.XmlSerializer()
.MsmqTransport();
SetLoggingLibrary.Log4Net(XmlConfigurator.Configure);
}
protected IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load<MyCustomNinjectModule>();
return kernel;
}
#endregion
}
with the ninject module being the usual format, ie:
public class MyCustomNinjectModule : NinjectModule
{
public override void Load()
{
Bind(typeof(ILogger<>)).To(typeof(Log4NetLogger<>));
...
}
}

Resources