How do I enrich logcontext with tracking id, when using a Hosted Service and ServiceScopeFactory - asp.net-core

We have .Net 6 WebApi and we are using Serilog. For regular http requests, we are using a custom middleware to enrich log context with a custom request tracing id. The Middleware inspects the http context request header for a tracing header. if its not available, it will add it and then push it to logcontext. So within that same request, whenever any service makes a logging call, the same tracing id is logged, allowing us to tie different log entries across service calls.
But we also have Hosted service under the same WebApi which reads request from a Channel and processes it. Within the hosted service, we are using ServiceScopeFactory and getting the required services within that scope. I am wondering, how can I use similar concept like the logcontext enrichment middleware so that I can add a tracing id to link all log entries happening across services, without needing to explicitly add that id within each service's log entry.
I saw that there is a Serilog.Enrichment.CorrelationId package, but this is dependent on httpContext. But in case of Hosted Service, there is no httpConext. So what options are available to link different log entries happening within that same scope? Also, to add, the services called within httprequest action method and hosted service are common.
Thanks!

Related

How can I send data to client-side after an API call when the caller is in another application

I have 2 web apps. One web app acts as a host (lets label as Host). All Web APIs resides here. Then the other web app calls those Web APIs (lets label as Client).
What I'm trying to accomplish is this:
Client calls a Web API using Jquery Ajax in Host and host processes this. After successful process, I want to be able to send some message in the HOST's client-side so I can update some UI.
That's the part I am unsure about. To notify the client-side of the Host so I can do some changes in UI, when the caller is in another app. I can't think of a way to pass some message so I can raise some popup, change some text, etc.
What I'm trying to accomplish is this: Client calls a Web API using Jquery Ajax in Host and host processes this. After successful process, I want to be able to send some message in the HOST's client-side so I can update some UI.
To achieve the requirement, you can try to integrate SignalR functionality into Apps.
Clients can connect to hub server, and clients can be added to two different groups, which provide a method for broadcasting messages to specified subsets of connected clients.
For more information about ASP.NET Core SignalR, you can check following docs:
https://learn.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-3.1
https://learn.microsoft.com/en-us/aspnet/core/signalr/groups?view=aspnetcore-3.1#groups-in-signalr

Publish event from service layer composed of web applications using service bus

I have read Why not publish NServiceBus messages from a web application and another similar question about this but I am not clear if this applies to service layer as well. For example, if the service layer is composed of web services or REST services built using WCF or Web API or any other way, should those services publish events or send commands? If those services are hosted in load balanced web servers, the problems outlined in the articles apply to this layer as well. How would the recommendation change or not change?
If I look from the definition of Event vs Command, the messages I am talking about are Events e.g. "a user was created" and so an event should be published. As a matter of fact, the service that created the user doesn't even know what else to do i.e. may be another application is supposed to create a customized portal for it and yet another application is supposed to send a welcome kit to the user. This would be an event and not a command. I guess I am hung up on the definition of a web application and application service when application service itself is composed of one or many web applications.
The definition of Web Application
A web application is an application that is accessed by users over a
network such as the Internet or an intranet.
However, to me, the users can be computers and thus web services are web applications and that is the reason for this question.
EDIT:
Let's consider a concrete example. An ASP.NET website (MVC or Web form - doesn't matter) displays the form to the operator, gets a post with data about user creation (Name, UserName, Password) and invokes a WCF service to create the user. In between website and WCF service we can put ServiceBus and send command to create the user (Request/Response) so that we get all the benefits described in the first article. WCF service is the actual business processing layer i.e. it would create the user. That is where I have the question. After the user is created, it should announce that a user has been created and other systems can react to it and do whatever they are supposed to do. So it fits perfectly the pattern of publish the message. However, the WCF service itself is a web application and thus has most of the traits of the web applications and thus the confusion.
As mentioned in the answer to the SO question you linked to, publishing event has more to do with where the actual processing takes places. Just as a side-note: it is not a matter of Send instead of Publish since that would imply that the two are interchangeable whereas they have rather different intentions. When you want to publish, you want to publish.
The same questions should arise if you find yourself publishing from your web-exposed integration layer: should you be performing the business processing in that code or rather sending it off to another endpoint for processing? Typically you should just send it off to another endpoint. You may even consider how you would perform the relevant action should anyone wish to invoke it. For instance, if you are publishing a UserCreatedEvent message it implies that you created a user. How would a user be created? Would I be forced to use the WCF / Web-Api layer or can I send a CreateUserCommand message on the bus that is processed by some application endpoint? If it is the former then you may need to rethink your design. However, if the latter you should be sending the command from your WCF / Web-Api anyway and the processing endpoint will perform the Publish bit :)
update:
My take on it is that it is more about cohesion / concerns. You would typically interact with your domain, from within your business, via a service bus for commands and events, and a simple query layer for reads. If you need to expose anything to a third-party (or simply via the web) then you use WCF / WS / Web-APi. The point is that you should try to avoid business processing in an integration endpoint (or in a front-end like a website). Business processing is better suited to application servers. There are usually exceptions to the rule but if you are in a position to influence the structure then you are in a better space.
The fact is, whatever code is truly responsible for performing the action should be the same which publishes the event. If you've got a MVC app and in the controller itself you're using Entity Framework to insert the User record, then that is exactly where the Publish should be, right after the SaveChanges call. If however, the controller calls a referenced binary or service which does the actions involved in the "add user" call, then the Publish should be there. My thought is the event should be right alongside the code that does the action whose event you are trying to publish.

Custom authentication, authorization and session for WCF

I have read about various implementations of authentication and authorization for WCF, starting from reusing some built in .NET and WCF features and ending with completely custom implementations.
But there are so many factors to take into account, so I'm confused about how to implement it for my intranet business application project.
Here is what I need:
- WCF .NET 4.5 services will be hosted in IIS 7 or newer.
Most probably, ASP.NET compatibility will be disabled.
Protocol will be HTTP with BasicHttpBinding, but it might need binary serialization to minimize traffic.
WCF method will receive a custom session ID which will be checked against a user session object in a database. No .NET sessions are allowed in this project.
After receiving the ID, the service will read the corresponding user data (including authorization flags to see if the user is allowed to execute the current operation) and validate it. If data is invalid, an exception will be thrown and the WCF operation won't be executed. If validation succeeds, the identity of the user will be stored in a current operation context (and also current thread principal) so it can be accessed by various components during the WCF operation execution.
All the authentication&authorization should be done transparently before the execution of the WCF operation - without additional efforts from programmers who will create the WCF methods.
I need access to the WCF operation name being executed, when I perform the auth validations, so I can throw an exception if the user does not have permissions to execute the operation.
testers will use SoapUI, so they'll need to be able to pass the session ID through standard SOAP or HTTP headers.
Which would be the most straightforward way to implement my auth routines? Should I use a custom binding? Custom behavior? Some kind of a built-in request event handler (which one exactly, and will they work if ASP.NET compatibility is disabled)? Authorization policy (seems a bit overkill because I won't be using most of its built-in features anyway)? Something else?
You can try making use of Message Inspectors. Your session ID can be passed like a token through SOAP or HTTP Headers and will be inspected by WCF through your defined behavior before it executes the actual service operation.
You can check the articles here and here, particularly focusing on the IDispatchMessageInspector interface which offers the "AfterReceiveRequest" and "BeforeReceiveReply" methods.

WCF Service hosted in Worker Role on Windows Azure that acts like a proxy and needs to call other services hosted in other Worker Roles

as you can see, I am relatively new on SO please don't kill me after posting this question :) I will do my best to describe the dilemma I am currently in.
I am creating something like a "Guardian Service" that is hosted on Windows Azure inside a Worker Role. This service has external ports, that can be accessed via HTTPS to allow clients to call it's service methods.
The WCF service is meant to call other services hosted in other Worker Roles that have only internal ports open, and which can be accessed only through the use of the Guardian Service. That's the main idea. Similar to a proxy or something.
I read already an excellent article from Jim O'Neil, what the caveats are when you try to access internal service points from within other WCF Services hosted in worker Roles:
His blog Troubleshooting Endpoints on a WCF Web Role
This is not the point for this question, and totally clear to me how to do that.
I have no idea at the moment, how I could do this, without implementing every contract from every single service I want to make accessible from within the Guardian Service to the outside world.
There must be a better way to decouple those things.
Any tips are appreciated.
Thank you.
I do not know the exact requirements for your project but I would say that what you are looking for is WCF Routing. I've used it in the past to redirect requests for different versions of Workflow instances.
The way it works is completely transparent to the client connecting to its endpoint. The router implementation must decide where to send the requests to, based on the request data (message headers and body).
In your case, if you are using SOAP and namespaces correctly, you might be able to base your decision on the message soap address and then send the request to the correct endpoint. You could also look at the Action property of the message.
Some links that might be useful:
http://msdn.microsoft.com/en-us/library/ee517423.aspx
http://www.codeproject.com/Articles/227699/RoutingService-on-Azure

WCF routing and service metadata

I'm building a WCF router which needs to act as a proxy for a number of internal web services (WCF and ASMX). The routing part is fairly straight-forward, but I can't understand how the service metadata exchange would work in this solution.
In other words: how would a client obtain metadata for an internal service behind the router? Do I need to manually supply WSDL files to the consumer? Can I somehow setup the router to return the metadata for an appropriate internal service?
Or perhaps my architecture is completely wrong?
I see 2 options here:
It may be an option to create a "non-transparent" proxy, if you don't want to expose the internal addresses. The advantage is that you can do more than just routing messages (i.e. such proxy may serve as a "security boundary", unwrapping ciphered messages and passing them plain to the internal endpoint). It can also provide an "interoperable level", exposing a WCF service as simple SOAP using same datatypes/message XML structure. The downside is that you'll have to update its code along with the proxied services
You may implement a WSDL rewriter. With it, you can mask the internal service URL on-the-fly - depending on your conditions, a simple string replace may or may not suffice.
Refer to:
Message Inspectors
IWsdlExportExtension
The same "router service" can also be used to get the individual WSDL for internal services behind the router.
Check out this thread
Have you considered using a simple HTTP Proxy instead? All WCF using REST or SOAP are at their core HTTP requests. It seems like the routing functionality (which I am assuming you are basing on hostname, URL path or parameters) could be performed by proxying the HTTP request without needing to understand the contents. ASP.Net will do a fairly good job of sanitizing incoming requests on its own, but you could always add additional custom filtering as necessary.