How to add Startup.cs in existing project .net5 - c#

I have an .net5 project and in .csproj file I have this:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
I added Microsoft.EntityFrameworkCore package to my prject.furturemore I created Dbcontext file like below:
using Domian;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace Mc2.CrudTest.Presentation.Front.Infrastructure
{
public class DataContext : DbContext
{
protected readonly IConfiguration Configuration;
public DataContext(IConfiguration configuration)
{
Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
// connect to sql server with connection string from app settings
options.UseSqlServer(Configuration.GetConnectionString("SqlServerConnection"));
}
public DbSet<Customer> Customers { get; set; }
}
}
since there wasn't any startup.cs file in my project ,I created one this way:
the namespaces of IApplicationBuilder and IWebHostEnvironment coudn't find.
I dont know whether I can use startup.cs file like.net core.3.1 or I shouldn't use startup.cs file in .net5 anymore.
And my program.cs file was formed this way:
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Mc2.CrudTest.Presentation.Front
{
public class Program
{
public static async Task Main(string[] args)
{
WebAssemblyHostBuilder builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
builder.Services.AddDbContext(options => options
}
}
}
In addtion my project is BlazorWebAssembly

First of all, don't use .NET 5. It reached End-of-Life on May 2022. That's almost a year ago. EOL means no support at all, for anything, from either Microsoft or NuGet authors. Not even security patches.
It was known from the start this would be a single-year or "Standard-Term" Support version (STS), supported only for 18 months. The Long-Term-Support version is .NET 6, supported until November 2024. LTS versions are supported for 3 years since release.
Second, you don't need Startup.cs in .NET 6 (or .NET 5). The methods found in Startup.cs were merged into Program.cs. You can write :
builder.Services.AddDbContext(options=>options
.UseSqlServer(builder.Configuration.GetConnectionString("SqlServerConnection")));
This is shown in all ASP.NET Core and EF Core tutorials, eg this Web API tutorial. In this tutorial, Program.cs contains :
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Notice that even Program.Main is missing. That's the entire file. This is possible through a few new C# features: top-level statements and implied usings.
If you don't like this style you can use --use-program-main to generate a Program.cs and Main method

First off, of course you should update to .NET6 or .NET7 if you can[1]. But if that's not practical for whatever reason, then of course you can use startup.cs. In fact I prefer to as well, out of habit (you can use it in .NET6 too; not sure about 7 but I assume so).
You can define startup.cs more or less the way you do, but you do need the right using's:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
Less obviously, in your program.cs you need
using Microsoft.AspNetCore;
...
public static async Task Main(string[] args)
{
...
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
...
}
Edit - After discussing with Amir in comments below it seems the scope of this problem is pretty different from what was originally asked. I suggest you spend some time in an example Blazor solution with a separate hosting project from the webassembly SPA project. Things will make a lot more sense after that.
[1] Microsoft IMO has done the world a disservice with its post-Framework policy of introducing breaking changes into each ASP.NET version so liberally. It's not always just a matter of retargeting. And that's especially true of Blazor which is still so immature. Certainly if security is a concern for this application you should be doing everything you can to upgrade, but in the real world isn't always that simple.

you should add blazerServerApp project which consist of program.cs and startup.cs which you looking for as shown below.

Related

.NET 6 Single-File ASP.NET template with Entity Framework Core

I am using the Visual Studio 2022/.NET 6 Razor pages template. It uses a top-level C# 10 program file. Program.cs looks something like this:
using Microsoft.EntityFrameworkCore;
using Data;
using Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMemoryCache();
builder.Services.AddRazorPages();
var settings = builder.Configuration.Get<AppSettings>();
builder.Services
.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.MapRazorPages();
app.Run();
My DBContext looks like this
public class ApplicationDbContext: DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
internal DbSet<MyModel> MyModels { get; set; }
protected override void OnModelCreating(ModelBuilder builder){ /* ... */ }
}
When I run dotnet ef migrations add InitialMigration -v, I get the following error:
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'Data'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'ApplicationDbContext'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
---> System.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Data.DatabaseContext.ApplicationDbContext]' while attempting to activate 'Data.DatabaseContext.ApplicationDbContext'.
Visual Studio Add-Migration also fails to build, but provides no stack trace.
The provided link indicated that I might be able to add an implementation of IDesignTimeDbContextFactory to contain some startup code that might work.
I created this class, but it also seems to do nothing.
public class ApplicationContext: IDesignTimeDbContextFactory<ApplicationDbContext>
{
ApplicationDbContext IDesignTimeDbContextFactory<SanDiegoContext>.CreateDbContext(string[] args)
{
IConfigurationRoot configuration = MyStaticConfigurationBuilder.GetConfig();
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseSqlServer(connectionString: configuration.GetConnectionString("DefaultConnection"));
return new ApplicationDbContext(optionsBuilder.Options);
}
}
Is it possible to use EF Core in .NET 6 without building a GetHostBuilder(string[]) method and a Startup class? If so, what am I doing wrong?
I made it work with the following steps:
Rebuild the project.
Make sure I was using Visual Studio Command Line Tools with the right project
Install Microsoft.EntityFrameworkCore.Design to my Web project
Make sure my project builds on its own with a standard CTRL-B or dotnet build
Then my startup looks like this:
using Microsoft.EntityFrameworkCore;
using Data;
using Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMemoryCache();
builder.Services.AddRazorPages();
var settings = builder.Configuration.Get<AppSettings>();
builder.Services
.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.MapRazorPages();
app.Run();
and the migration attempts to scaffold as usual

How to exclude a .NET 6 Minimal API from code coverage?

I maintain a class library which contains several reference implementations to demonstrate how the library should be used. I have reference implementations for .Net Framework, core, .NET 5 and now I have added a reference implementation for .NET 6 using minimal APIs.
For all of my other reference implementations I have added the ExcludeFromCodeCoverage attribute using System.Diagnostics.CodeAnalysis to all of their containing classes. How would I do something similar for a .NET 6 minimal API?
My program.cs looks like this:
using Microsoft.AspNetCore.Mvc;
using SharedDataLayer.Repositories;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<PaymentRepository>();
var app = builder.Build();
app.MapGet("/Payments", ([FromServices] PaymentRepository repo) =>
{
return repo.GetPayments();
});
app.Run();
Your Program.cs shoud look like this:
using Microsoft.AspNetCore.Mvc;
using SharedDataLayer.Repositories;
using System.Diagnostics.CodeAnalysis;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<PaymentRepository>();
var app = builder.Build();
app.MapGet("/Payments", ([FromServices] PaymentRepository repo) =>
{
return repo.GetPayments();
});
app.Run();`
[ExcludeFromCodeCoverage]
public partial class Program { }
I've tested out the suggestions from #PanagiotisKanavos and #Tolvic in the comments on the initial question and can confirm that adding the following to the top of your program.cs does work and the file is excluded from code coverage.
using System.Diagnostics.CodeAnalysis;
[assembly: ExcludeFromCodeCoverage]
using System.Diagnostics.CodeAnalysis;
[assembly: ExcludeFromCodeCoverage]
worked for me

How to fix the bot configuration when migrating settings form .bot file to appsettings

I ran into a problem when trying to deploy my bot to Azure. The following error was given when I tried to create the Azure resources: error: InvalidBotData, message: Version: Bot Version has an invalid value. I dug around a little bit and found the that my bot is version 4.3 while now you need 4.4 to deploy…
I found that Mircosoft already has a solution for the problem found here: https://learn.microsoft.com/bs-latn-ba/azure/bot-service/bot-file-basics?view=azure-bot-service-4.0&tabs=csharp I followed the steps, I also changed the way QnAmaker and Luis are called. But when I run the application I get the following error: System.InvalidOperationException: Unable to resolve service for type 'VacancyBot.VacancyBot.Services.BotServices' while attempting to activate 'VacancyBot.VacancyBotBot'.
I realized that the bot was not being added anywhere anymore so I tried adding it with services.AddSingleton<VacancyBotBot>() but that did not work. Adding it as an Transient also does not work.
The part that normally adds the bot is this:
var secretKey = Configuration.GetSection("botFileSecret")?.Value;
var botFilePath = Configuration.GetSection("botFilePath")?.Value;
var botConfig = BotConfiguration.Load(botFilePath ?? #".\nlp-with-luis.bot", secretKey);
services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot config file could not be loaded. ({botConfig})"));
var connectedServices = new BotServices(botConfig);
services.AddSingleton(sp => connectedServices);
But this does not work anymore because, as aspected, the .\nlp-with-luis.bot cannot be found. (I did not delete the .bot file for real yet, but it doesn't use it anymore now I guess?).
I was wondering if anybody happens to know how to add the bot, or alter the BotConfiguration in a way that it works again. I really hope this is possible! If someone needs to see more code please say so and I will try to provide it (:
I forgot to add that I tried putting back "botFilePath": "VacancyBot.bot",
"botFileSecret": "", in the appsettings file, but results into getting the same error in Azure again...
The .bot file can still be used, but it looks like you're trying to use a combination of .bot file and appsettings.json. Let's get you straightened out.
Starting with appsettings.json: You no longer need botFilePath or botFileSecret. Instead, structure your appsettings.json like below:
{
"MicrosoftAppId": "",
"MicrosoftAppPassword": "",
"LuisAppId": "",
"LuisAPIKey": "",
"LuisAPIHostName": ""
}
The MicrosoftAppId and MicrosoftAppPassword are now pulled in through a ConfigurationCredentialProvider.cs file, which will later be added as a singleton in Startup.cs. The ConfigurationCredentialProvider should look like below:
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Extensions.Configuration;
namespace CoreBot1
{
public class ConfigurationCredentialProvider : SimpleCredentialProvider
{
public ConfigurationCredentialProvider(IConfiguration configuration)
: base(configuration["MicrosoftAppId"], configuration["MicrosoftAppPassword"])
{
}
}
}
Short, sweet and to the point. Finally, structure your startup.cs like below, to add both the bot and the ICredentialProvider:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Integration.AspNet.Core;
using Microsoft.Bot.Connector.Authentication;
using Microsoft.Extensions.DependencyInjection;
using CoreBot1.Bots;
using CoreBot1.Dialogs;
namespace CoreBot1
{
public class Startup
{
public Startup()
{
}
// 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);
// Create the credential provider to be used with the Bot Framework Adapter.
services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();
// Create the Bot Framework Adapter with error handling enabled.
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
// Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
services.AddSingleton<IStorage, MemoryStorage>();
// The Dialog that will be run by the bot.
services.AddSingleton<MainDialog>();
// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
services.AddTransient<IBot, DialogAndWelcomeBot<MainDialog>>();
}
// 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();
}
else
{
app.UseHsts();
}
app.UseDefaultFiles();
app.UseStaticFiles();
//app.UseHttpsRedirection();
app.UseMvc();
}
}
}

Is there an in memory job storage package for Hangfire?

I have a console application to test HangFire. Here is the code:
using System;
using Hangfire;
namespace MyScheduler.ConsoleApp
{
internal static class Program
{
internal static void Main(string[] args)
{
MyMethod();
Console.WriteLine("[Finished]");
Console.ReadKey();
}
private static void MyMethod()
{
RecurringJob.AddOrUpdate(() => Console.Write("Easy!"), Cron.Minutely);
}
}
}
But it throws an exception on runtime:
Additional information: JobStorage.Current property value has not been
initialized. You must set it before using Hangfire Client or Server
API.
So I need a job storage to run this. But all examples in SQL storage etc. Is there any way to run this example with some kind of memory storage?
JobStorage.Current = new SqlServerStorage("ConnectionStringName", options);
// to
JobStorage.Current = new MemoryDbStorage(string.Empty, options);
You can use Hangfire.MemoryStorage for this.
Simply add this nuget package.
And then you can use it like -
GlobalConfiguration.Configuration.UseMemoryStorage();
For NET Core (web application):
Just to make it very obvious because it wasn't obvious to me.
Install following nuget packages:
Hangfire.AspNetCore (v1.6.17 atow)
Hangfire.MemoryStorage.Core (v1.4.0 atow)
In Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// other registered services
...
services.AddHangfire(c => c.UseMemoryStorage());
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// other pipeline configuration
...
app.UseHangfireServer();
app.UseMvc();
}
Anything less than above and my enqueued method did not fire.
As Yogi said, you can use Hangfire.MemoryStorage or Hangfire.MemoryStorage.Core (for .Net Core).
What is missing in that answer is the complete code (for .Net Core) that needs to be put inside ConfigureServices(..) :
var inMemory = GlobalConfiguration.Configuration.UseMemoryStorage();
services.AddHangfire(x => x.UseStorage(inMemory));
Just for the sake of completeness the author of the Hangfire library has added a new package titled Hangfire.InMemory the version of which is available on Nuget. The repository readme positions it as targeting production use. A quote github repo URL is as follows "..an efficient transactional in-memory storage for Hangfire with data structures close to their optimal representation. The result of this attempt should enable production-ready usage of this storage implementation and handle particular properties of in-memory processing.."
The familiar configuration concept applies here as well:
GlobalConfiguration.Configuration.UseInMemoryStorage();
I personally added it as follows:
services.AddHangfire(configuration => { configuration.UseInMemoryStorage(); });

UseSqlServer method missing MVC 6

I am trying to implement Entity Framework 7 in MVC 6, and on this page here it says to do
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MusicStoreContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
But for me, the UseSqlServer method isn't visible? Anyone know how to make it visible? Or is this an old way of configuring entity framework?
My startup.cs file looks like this
using FluentValidation;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
namespace me.namespace.project
{
public class Startup
{
public static IConfiguration Configuration { get; set; }
public Startup(IHostingEnvironment env)
{
// Setup configuration sources.
Configuration = new Configuration()
.AddJsonFile("config.json")
.AddEnvironmentVariables();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// entity framework
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<DataContext>();
}
}
}
Install Microsoft.EntityFrameworkCore.SqlServer 1.0.1 package works for me
Version of Microsoft.EntityFrameworkCore is 1.1.0
UseSqlServer is an extension method in the namespace Microsoft.Data.Entity so you need to import that in your code, like this:
using Microsoft.EntityFrameworkCore;
Since this has been posted, assemblies have been renamed. As part of EntityFrameworkCore you now need to add a using statement the following
using Microsoft.EntityFrameworkCore;
And the .UseSqlServer extension method to configure your context will become available
It's a NuGet Packages Problem
Install the following Packages and with its Proper Versions
1. Microsoft.EntityFrameworkCore(Latest Version)
2. Microsoft.EntityFrameworkCore.SqlServer(1.0.4 Version)

Categories

Resources