How to configure an external SOAP service in a net core 2.2 project - wcf

I have a project developed in .net core 2.2.
You need to use a WCF in .Net Framework.
The inclusion of WCF and Reference.cs went well. The service is Ok, as a connected service.
However I am getting a dependency injection error:
microsoft.extensions.dependencyinjection.servicelookup.callsite factory.create argument callsite(type servicetype, type implementationtype, callsitechain callsitechain, parameterinfo[] parameters, bool throwifcallsitenotfound)
Performing searches on the internet, some answers were related to the configuration of Startup.cs and Program.cs:
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddSessionStateTempDataProvider()
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = this.GetJsonSerializerContractResolver();
options.SerializerSettings.DateFormatString = this.GetJsonSerializerDateFormatString();
});
this.ConfigureIoC(services);
}
private void ConfigureIoC(IServiceCollection services)
{
this.ConfigureHelpers(services);
this.ConfigureUnitOfWorks(services);
this.ConfigureFacades(services);
this.ConfigureBusinessServices(services);
this.ConfigureServiceFilters(services);
this.ConfigureRestConsumers(services);
}
private void ConfigureHelpers(IServiceCollection services)
{
services.AddScoped(typeof(IHpUrl), typeof(HpUrl));
services.AddScoped(typeof(IHpArvoreProduto), typeof(HpArvoreProduto));
}
My doubt is whether I would need only one method:
private void ConfigureSoaps(IServiceCollection services)
{
services.AddScoped(typeof(ISoapBla), typeof(SoapBla));
}
Since in some responses from the Web, the use of SoapCore among other solutions has been suggested.

Related

'ConfigureServices returning an System.IServiceProvider isn't supported.' in .NET Core 3.1 using Autofac

I want to use autofac injection instead of default .net core solution.
Here is my startup file :
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc(option => option.EnableEndpointRouting = false) ;
var cb = new ContainerBuilder();
cb.RegisterModule<mydependecymodule>();
cb.Populate(services);
var container = cb.Build();
return new AutofacServiceProvider(container);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseStatusCodePages();
app.UseStaticFiles();
app.UseMvc(routes=>routes.MapRoute("default","/{controller=home}/{action=index}"));
}
And here is my program.cs
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
}).UseServiceProviderFactory(new AutofacServiceProviderFactory());
But when I run my application I get this error in my main method:
System.NotSupportedException: 'ConfigureServices returning an System.IServiceProvider isn't supported.'
In ASP.NET Core 3.0 the ASP.NET Core hosting model changed and you can't return an IServiceProvider anymore. This is documented in the Autofac docs for integrating with ASP.NET Core 3.0+.
You have to switch your ConfigureServices to be void, and if you want to register stuff directly with Autofac you need to use ConfigureContainer. You also need to register the AutofacServiceProviderFactory in your Program.Main method when you construct the host. There are examples in the documentation showing how to do this.

How to validate all registered types in ASP.NET Core DI?

I want to check that the type registrations I established in Startup.cs are all valid at runtime (either when starting up the service or as part of a test suite). There's a feature like this in Lamar and other containers.
ASP.NET Core 3.x actually introduced a feature for scope and provider validation. Both of these are useful in different contexts (see the below post and sample code).
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
options.ValidateOnBuild = true;
});
https://andrewlock.net/new-in-asp-net-core-3-service-provider-validation/
You can iterate the services that you want to validate, and try to initialize a service with GetRequiredService<T>. It will throw an exception if there is something wrong. More info on
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.serviceproviderserviceextensions.getrequiredservice?view=aspnetcore-2.2
The IServiceCollection is actually enumerable over ServiceDescriptor which contains type information on the registered service and implementation. The service collection isn't usually registered, but it should be possible to capture both the service collection and service provider in a hosted service.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddServicesValidation();
}
The right extension method can capture the services collection without actually registering it (which feels "safer").
public static class ValidateServicesExtensions
{
public static IServiceCollection AddServicesValidation(this IServiceCollection services)
{
services.AddHostedService<ValidateServices>(provider => new ValidateServices(services, provider));
return services;
}
}
Now, the hosted service can iterate over the registered services & implementations. Although, this code bombs on the first generic IOptions<TOption>, but I'm sure we can figure something out?
ValidateServices.cs
public class ValidateServices : BackgroundService
{
private readonly IServiceCollection services;
private readonly IServiceProvider provider;
public ValidateServices(
IServiceCollection services,
IServiceProvider provider
)
{
this.services = services;
this.provider = provider;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
using var scope = provider.CreateScope();
foreach (var service in services)
{
_ = scope.ServiceProvider.GetRequiredService(service.ServiceType);
}
return Task.CompletedTask;
}
}

SignalR Core, error: The 'Sec-WebSocket-Accept' header value 'u1mOHwcpjPm7txGcxCm1jVmOgjo=' is invalid

I'm trying to implement SignalR Core in a .Net core 2.0 Web app, and implement client side in a Xamarin.Android application.
I created a fresh .Net core 2.0 Web app solution and imported Microsoft.AspNetCore.SignalR and setup the Startup.cs file like in this sample
https://github.com/aspnet/SignalR-samples/blob/master/ChatSample/ChatSample/Startup.cs
My code:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseFileServer();
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("chat");
});
}
}
This project is deployed to Amazon Elastic Bean Stalk.
On the client side, I have imported Microsoft.AspNetCore.SignalR.Client and I initialize a connection like in this sample
https://github.com/aspnet/SignalR-samples/blob/master/XamarinAndroidChatClient/XamarinAndroidChatClient/MainActivity.cs
My code:
public async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
hubConnection = new HubConnectionBuilder()
.WithUrl("http://*******.eu-central-1.elasticbeanstalk.com/chat")
.Build();
try
{
await hubConnection.StartAsync();
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
But .StartAsync() throws this exception:
{System.Net.WebSockets.WebSocketException (0x80004005): The 'Sec-WebSocket-Accept' header value 'LNqQiPhES/zOwW10TMji4AVvvoA=' is invalid.
at System.Net.WebSockets.WebSocketHandle.ValidateAndTrackHeader (System.String targetHeaderName, System.String targetHeaderValue, System.String foundHeaderName, System.String foundHeaderValue, System.Boolean& foundHeader) [0x0002c] in <6c708cf596db438ebfc6b7e012659eee>:0 `
I found this post which was related to Amazon ELB and setting up websockets
(Elastic Beanstalk stripping Sec-WebSocket-Accept header)
Also found this post with same problem
(https://forums.aws.amazon.com/thread.jspa?messageID=613220)
As in this post, things are working fine if I choose "LongPolling" as transport
hubConnection = new HubConnectionBuilder()
.WithUrl("http://*******.eu-central-1.elasticbeanstalk.com/chat")
.WithTransport(TransportType.LongPolling)
.Build();
This guy was suggested to switch LoadBalancer listeners from HTTP to TCP, I tried this, but issue is still remaining
Also I read a suggestion to install websockets in ISS on AWS Management Console, but I can't find this option anywhere?
Any kind of help or suggestions are appreciated
You'll need to log onto the Elastic BeanStalk server and enable the Websocket Protocol on in the server roles in Server Manager, this fixed it for me.

Enable / Disable SSL on ASP.NET Core projects in Development

On an ASP.NET Core project, I am using SSL in Production so I have in Startup:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc(x => {
x.Filters.Add(new RequireHttpsAttribute());
});
// Remaining code ...
}
public void Configure(IApplicationBuilder builder, IHostingEnvironment environment, ILoggerFactory logger, IApplicationLifetime lifetime) {
RewriteOptions rewriteOptions = new RewriteOptions();
rewriteOptions.AddRedirectToHttps();
builder.UseRewriter(rewriteOptions);
// Remaining code ...
}
It works fine in Production but not in Development. I would like to either:
Disable SSL in Development;
Make SSL work in Development because with current configuration it is not.
Do I need to set any PFX files on my local machine?
I am working on multiple projects so that might create problems?
You can configure a service using the IConfigureOptions<T> interface.
internal class ConfigureMvcOptions : IConfigureOptions<MvcOptions>
{
private readonly IHostingEnvironment _env;
public ConfigureMvcOptions(IHostingEnvironment env)
{
_env = env;
}
public void Configure(MvcOptions options)
{
if (_env.IsDevelopment())
{
options.SslPort = 44523;
}
else
{
options.Filters.Add(new RequireHttpsAttribute());
}
}
}
Then, add this class as a singleton:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
var builder = services.AddMvc();
services.AddSingleton<IConfigureOptions<MvcOptions>, ConfigureMvcOptions>();
}
Concerning the SSL point, you can easily use SSL using IIS Express (source)
If you don't want to use IIS Express then delete the https-address in Project Properties -> Debug section -> Under "Web Server Settings" -> Uncheck "Enable SSL".
just comment this line:
rewriteOptions.AddRedirectToHttps();
or in new versions of .Net core on Startup.cs comment:
app.UseHttpsRedirection();
Using #if !DEBUG, like below:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc(x => {
#if !DEBUG
x.Filters.Add(new RequireHttpsAttribute());
#endif
});
// Remaining code ...
}

Convention based approach for configuring services based on Operating System in Startup.cs

I recently created an ASP.NET service using 1.0.0-rc1-update1 on coreclr (x64). So, the service is capable of running on all supported Operating Systems; very cool! My service just exposes a simple "TODO" API and uses the Entity Framework 7.0 ORM. For persistence, it employs a Sqlite DB on Linux and SQL Server DB on Windows.
I am wondering if there is a convention based approach to allow Startup.cs to handle differing service configurations for the various Operating Systems? For example, my EF configuration differs because it uses Sqlite on Linux and SQL Server on Windows.
The following article does detail some convention based approaches to configuration, but it seems to only allow for different methods for the higher level abstractions of "Development", "Staging", "Production" environments:
https://docs.asp.net/en/latest/fundamentals/environments.html
Currently, I am just injecting the IRuntimeEnviroment in the constructor of Startup.cs and saving it. Then, when ConfigureServices is invoked, I check the OperatingSystem property of the IRuntimeEnvironment and adjust the EF configuration accordingly (my full Startup.cs provided below)...
Any guidance on other (or recommended) approaches would be greatly appreciated.
public class Startup
{
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
public IConfigurationRoot Configuration { get; set; }
public IRuntimeEnvironment RuntimeEnv { get; set; }
public Startup(IHostingEnvironment env, IRuntimeEnvironment runtimeEnv)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
RuntimeEnv = runtimeEnv;
}
public void ConfigureServices(IServiceCollection services)
{
if (RuntimeEnv.OperatingSystem == "Windows")
{
var connectionString = Configuration["Data:DefaultConnection:ConnectionString"];
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<TodoContext>(options => options.UseSqlServer(connectionString));
}
else if (RuntimeEnv.OperatingSystem == "Linux")
{
var connectionString = Configuration["Data:DefaultConnection:SqlLiteConnection"];
var path = PlatformServices.Default.Application.ApplicationBasePath;
services.AddEntityFramework()
.AddSqlite()
.AddDbContext<TodoContext>(options => options.UseSqlite("Filename=" + Path.Combine(path, "TodoApp.db")));
}
services
.AddMvcCore(options =>
{
options.OutputFormatters.Clear();
options.OutputFormatters.Add(new HttpNotAcceptableOutputFormatter());
options.OutputFormatters.Add(new HttpNoContentOutputFormatter());
})
.AddJsonFormatters();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseIISPlatformHandler();
app.UseMvc();
loggerFactory.AddConsole(minLevel: LogLevel.Verbose);
loggerFactory.MinimumLevel = LogLevel.Debug;
}
}