Do we really need app.Run(); in a minimal Web API? [duplicate] - c#

This question already has answers here:
Whats the point in calling app.Run() multiple times in ASP.NET Core?
(2 answers)
Closed last month.
So I've been studying the documentation of.net Core Middleware and it mentions there are three types of request delegates: Run, Use and Map. I use app.MapGet() to handle a few specific routes and I have a few app.Use() to filter some incoming requests for various purposes. And I have an app.Run() in my code also. And I wonder why it is actually needed.
If I remove it, the site won't work with a "HTTP Error 500.30 - ASP.NET Core app failed to start" message so I seem to need it.
But then I see this code example:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
And I can't help but wonder why this has an extra app.Run() in it, with parameters. I'm trying to understand why I would use this second app.Run() in my code.
So, what is the use case for having multiple app.Run() commands in my code?

If you check the source code then you will see the second app.Run() is for running the application and listening a URL (check the summary)
/// <summary>
/// Runs an application and block the calling thread until host shutdown.
/// </summary>
/// <param name="url">The URL to listen to if the server hasn't been configured directly.</param>
public void Run([StringSyntax(StringSyntaxAttribute.Uri)] string? url = null)
{
Listen(url);
HostingAbstractionsHostExtensions.Run(this);
}
And the first app.Run(async context => actually it's a wrapper for app.Use. Below is the source code for first one
namespace Microsoft.AspNetCore.Builder;
/// <summary>
/// Extension methods for adding terminal middleware.
/// </summary>
public static class RunExtensions
{
/// <summary>
/// Adds a terminal middleware delegate to the application's request pipeline.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> instance.</param>
/// <param name="handler">A delegate that handles the request.</param>
public static void Run(this IApplicationBuilder app, RequestDelegate handler)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
if (handler == null)
{
throw new ArgumentNullException(nameof(handler));
}
app.Use(_ => handler);
}
}
So let's go back to your question. If we don't have the second app.Run() how to run an application.

Related

How to run Hangfire as a separate process from the main web application?

I am experiencing a big performance hit with Hangfire running on the same app pool as my web application and our site has become terribly slow with CPU sitting at 96% constantly. I have looked at the Hangfire documentation and there is a way to run hangfire separate as a console or windows service. However, I do not understand how to achieve this and still get the dashboard. I have created a service as described on this link Here. Below is the current setup
Startup
[assembly: OwinStartup(typeof(MyProject.FrontEnd.Startup))]
namespace MyProject.FrontEnd
{
/// <summary>
///
/// </summary>
public class Startup
{
/// <summary>
///
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app)
{
app.UseHangfireAspNet(GetHangfireServers);
app.UseHangfireDashboard();
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.Use<RememberMeTokenMiddleware>();
.........
}
private IEnumerable<IDisposable> GetHangfireServers()
{
GlobalConfiguration.Configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage("eCertDb");
yield return new BackgroundJobServer();
}
If I comment only app.UseHangfireAspNet(GetHangfireServers); the dashboard and application breaks. I get the error
JobStorage.Current property value has not been initialized. You must
set it before using Hangfire Client or Server API
. If I comment app.UseHangfireDashboard();, now whereever I have implementation of Hangfire it breaks, e.g. in my business layer
BackgroundJob.Enqueue<DocumentServiceWorker>(_ => _.PublishDocument(application.ApplicationReferenceNo, false));
The problem is how do I still have the above calls in the main application if hangfire is running in a different process? How do I still get the dashboard if I am running Hangfire as a Windows Service, do I need a separate site?
I found a project that essentially answers my question. This is how I changed my code to simply setting the UseSqlServerStorage for the client.
public class Startup
{
/// <summary>
///
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app)
{
GlobalConfiguration.Configuration.UseSqlServerStorage("xxxx");
app.UseHangfireDashboard();
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
.......
}
For the Windows Service I used the provided example from the Hangfire blog.
Example

SignalR C# (both client and Hub)-strongly typed example

SignalR C# - Checking if someone could forward me to a SIMPLE example of C# SignalR that uses Strongly Typed calls to client methods via Hub (not passing a string) and also does NOT have javascript involved but the client side is in C# and lastly has an API controller endpoint exposed for an external call to the Hub side.
In .NET Core Web App you can inject strongly typed signalR hub context like this
public interface IClient
{
Task ReceiveMessage(string message);
}
public class DevicesHub : Hub<IClient>
{
}
public class HomeController : ControllerBase
{
private readonly IHubContext<DevicesHub, IClient> _devicesHub;
public HomeController(IHubContext<DevicesHub, IClient> devicesHub)
{
_devicesHub = devicesHub;
}
[HttpGet]
public IEnumerable<string> Get()
{
_devicesHub.Clients
.All
.ReceiveMessage("Message from devices.");
return new string[] { "value1", "value2" };
}
}
if you want a tutorial you can use this link
https://darchuk.net/2019/07/19/signalr-strongly-typed-hubs/
communication between client and server. The general process that is followed won't allow to have strongly typed calls on the server and also in client code. We will look into how to make strongly typed calls on the server through interface and client end through TypeScript.
SignalR - making strong type on server side code
Since client-side methods are very dynamic in nature, so calling those from server side behaves similarly to allow any calls.
SignalR Hubs are derived from Microsoft.AspNet.SignalR.Hub class, there is also a generic version available to follow typed items.
Ex:
The interface is the replication of possible calls that would be received on the client end and calling of client-side methods on server code.
/// <summary>
/// Client(JS) side chatting interface callbacks.
/// </summary>
public interface IChatHub
{
/// <summary>
/// Gets the online users.
/// </summary>
/// <param name="chattingUsers">The chatting users.</param>
void GetOnlineUsers(IEnumerable<ChatAvailableUserOrGroup> chattingUsers);
/// <summary>
/// Determines whether the user is typing.
/// </summary>
/// <param name="userFullName">Full name of the user.</param>
void IsTyping(string userFullName);
/// <summary>
/// Member initialization through login.
/// </summary>
/// <param name="isSuccess">if set to <c>true</c> success login.</param>
void Login(bool isSuccess);
}
The above interface can be implemented on generic hub inheritance.
/// <summary>
/// SignalR Hub for chat application.
/// </summary>
public class ChatHub
: Hub<IChatHub>
{
}
After implementation of an interface on Hub, the IntelliSense would come automatically.
Clients.Caller.IsTyping("viku");
That is all on server-side code implementation.
Strong type implementation on the client-side.
The calls of server and client-side callbacks need to be wrapped under the interface. The calls are wrapped with server and client properties. Let's have a look at the interface.
interface SignalRExtended extends SignalR {
chatHub: ChatHub;
}
interface ChatHub
extends HubConnection {
client: { // callbacks on client side through server
GetOnlineUsers(json: string);
ReceiveMessage(message: Model.ChatReceiveMessage);
IsTyping(connectionId: string, message: string);
Login(): boolean;
UserChatHistory(chattingHistory);
};
server: { // Calling of server side hubs
login(): () => void;
sendPrivateMessage(toUserId: string, message: string);
chatHistory(toUserId: number);
groupChatHistory(toGroupId: number);
sendGroupMessage(toGroupId: number, message: string);
userTyping(targettedUserOrGroup: number, requestType: string);
markAsRead(messageIds: Array<number>, targetedUserOrGroup: number, requestType: ChatSourceType);
}
}
The TypeScript gets a property can be created and parsed based on the above interface.
get ChatHub(): ChatHub {
return <ChatHub>(<any>$.connection).chatHub;
}
Now, through the above property, we can access all methods of server and client calls with IntelliSense on TS.
The shown example is Skelton of the implementation but it can give an idea of how to make SignalR strongly typed.

Equivalent of ServiceBase.OnCustomCommand in BackgroundService in .NET Core / .NET 5

I have created a Windows Service in .NET Core (also in .NET 5) using a BackgroundService worker, running it as a Windows Service using the IHostBuilder.UseWindowsService() call.
My question is, how do I capture Windows Service commands such as
sc.exe control <my service name> 200
As far as I have been able to tell, there is no equivalent to the old ServiceBase.OnCustomCommand that I can capture in this new way of building Windows Services.
Any help on how to capture those commands would be appreciated. Even if the answer is just "go back to using ServiceBase for your Windows Service".
Thanks!
For anyone still looking for an answer. See this answer on github for a solution
It is basically about to register a custom IHostLifetime implementation:
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
if (WindowsServiceHelpers.IsWindowsService())
services.AddSingleton<IHostLifetime, CustomService>();
})
The actual implementation may be inheriting from WindowsServiceLifetime where you can override the OnCustomCommand method:
/// <summary>
/// Will handle custom service commands
/// </summary>
/// <param name="command">The command message sent to the service.</param>
protected override void OnCustomCommand(int command)
{
_logger.LogInformation("Received custom service control command: {0}", command);
switch (command)
{
case PreShutdownCommandCode:
// Handle your custom command code
break;
default:
base.OnCustomCommand(command);
break;
}
}

Postsharp AOP MethodInterception Aspect Not Working

I was trying to add a Permission based Attribute to be used by an existing Windows application built with WPF that I should work on.
the idea was to intercept the calls to the Canexecute methods of certain commands and return false -which would disable the buttons-
so I made a simple example on a solution where I have added the Nuget Package of Postsharp and override the OnInvoke Method as follows:
[Serializable]
public class PermissionBasedAttribute : MethodInterceptionAspect
{
public string PermissionName { get; private set; }
public PermissionBasedAttribute (string permissionName)
{
PermissionName = permissionName;
}
/// <summary>
/// Upon invocation of the calling method, the PermissionName is checked.
/// If no exception is thrown, the calling method proceeds as normal.
/// If an exception is thrown, the virtual method MethodOnException is called.
/// </summary>
/// <seealso cref="MethodOnException(SecurityPermissionException)"/>
public override void OnInvoke(MethodInterceptionArgs args)
{
try
{
/*
* some logic to check the eligibility of the user, in case of
not authorised an exception should be thrown.
*/
args.Proceed();
}
catch (SecurityPermissionException ex)
{
args.ReturnValue = false;
// MethodOnException(ex);
}
}
/// <summary>
/// Method can be overridden in a derived attribute class.
/// Allows the user to handle the exception in whichever way they see fit.
/// </summary>
/// <param name="ex">The exception of type SecurityPermissionException</param>
public virtual void MethodOnException(SecurityPermissionException ex)
{
throw ex;
}
}
anyway , every thing works fine within the small example with different approaches in the simple example like using devexpress or not.
but when added to the existing application it does not work at all, to be more precise: the OnInvoke method is never hit, while the Constructor of the Attribute is already being called.
I am not sure what is wrong, but an additional information is that I found out that the existing solution was utilizing Postsharp already for logging aspects.
so I have used the exact same version as the one used by the Project which is 4.2.26 by choosing this version from the Nuget Package Manager.
Another thing I have tried is that i have implemented the CompileTimeValidate method and purposefully added a code that should raise an exception upon build.
in the Small -Working- example it has raised an exception upon build.
while in the Existing application where it has not worked yet. upon build it does not raise any exception !!!.
Update:
I am Using at as follow:
[PermissionBasedAttribute("Permission1") ]
public bool CanShowView()
{
return true;
}
It turns out that Post Sharp was disabled in this project !!! I Installed the Post sharp Extension, then went to Post Sharp Section i found that it was disabled, once enabled it worked out fine

WebDriver Actions.Perform() or Actions.Build().Perform()

I use Selenium2 WebDriver with C#
Actions.Build - returns a composite IAction which can be used to perform the actions. (IActions has a Perform method to execute the actions)
Actions.Perform - Performs the currently built action.
In most of the examles use Actions like this:
new Actions(IWebDriverObj).actions...Build().Perform()
but this works as well
new Actions(IWebDriverObj).actions...Perform() //no Build before Perform
Is it necessary to use the Build() before the Perform() or Build() is for some compatibility purpose only?
Thanks in advance for the answers
Always keep in mind that Selenium is open source.
The source of WebDriver/Interactions/Actions.cs is here, clearly you can see Perform() includes Build(), so the answer is no, you don't need to build before perform, unless you want to pass the built IAction around without performing.
/// <summary>
/// Builds the sequence of actions.
/// </summary>
/// <returns>A composite <see cref="IAction"/> which can be used to perform the actions.</returns>
public IAction Build()
{
CompositeAction toReturn = this.action;
this.action = new CompositeAction();
return toReturn;
}
/// <summary>
/// Performs the currently built action.
/// </summary>
public void Perform()
{
this.Build().Perform();
}
Also, for anyone else reading this post:
Java binding: build() is included in perform(). Source: interactions/Actions.java
Ruby/Python: only have perform, no such thing called build. Source: action_chains.py, action_builder.rb
Actually, the .perform() includes a .build().
So you can only write : new Actions(IWebDriverObj).actions....perform()

Categories

Resources