How to use both IHttpClientFactory and Typed HttpClient? - asp.net-core

I have a typed HttpClient and (let's say) another service/class that uses IHttpClientFactory to get a HttpClient instance.
To register IHttpClientFactory, I inject it as services.AddHttpClient(). And to register typed clients, I go with services.AddHttpClient<MyTypedClient>
My question is, do you think there will be a problem if I use both of the use cases. Any impact on HttpMessageHandler pool?
Thanks,
Cem.

Simply, no. You can use whatever you want. IHttpClientFactory handles the collection of HttpMessageHandler instances. When you inject a typed client, what's actually happening is that IHttpClientFactory is invoked, and new HttpClient instance is created, and its handler is set to the either an already created HttpMessageHandler instance or a new instance.
In other words, it's mostly syntactic sugar. IHttpClientFactory is invoked in either case, and it always creates a new HttpClient instance, setting the handler to one that's tracking, based on name. A "typed" client is really just a "named" client, with the type as the name, and all clients are in effect "named" because it's all being stored in a ConcurrentDictionary, where the name is the key.

Related

WCF Custom Class Arguments

I have a WCF method which takes an argument that is a custom class, say,
void MyWCFMethod(MyCustomClass MethodArgument)
In the above, MyCustomClass has a number of constructor overloads. The service has a reference to the class but not the client. I want to allow the client to use the other overloads but the default constructor is the only one that seems to be allowed. Is there a way to do this?
You can certainly do this, but I think it is important to know why the Data Transfer Objects (DTOs) do not expose logic over the service reference.
The WSDL\XSD metadata that is used in order to generate the client proxy to access the WCF Service only describes the web service by the operations exposed and the datatypes exchanged.
Specifically, XSD only describes the structure of your DTOs and not the logic - that is why there is only the default constructor and public properties/fields available on the client proxy.
So the solution is to put all of your custom classes exchanged between the client and service in a separate shared library. This way both sides of the wire have access to the additional logic (like your parameterized constructors) that you could not obtain via WSDL\XSD.
I guess - no!
As I understand MyCustomClass is data contract and marked by [DataContract] attribute.
So WCF runtime will use DataContractSerializer (by default) to deserialize data from received message to the instance of object.
So where can DataContractSerializer get additional parameters for your specific constructors?
Instance of data contract must have public parameter-less constructor to be instantiated.
But maybe you can write own serializer (but keep in mind that DataContractSerializer cannot be inherited)... and provide additional data to constructor. But if you can get that information somewhere just do it in public parameter-less constructor of your data contract.
So I guess you are doing something wrong. Try to specify what is the goal to pass data in constructor in your case. Maybe your app can use some another solution.

WCF Service - Single Instance - Static constructor

Just want to confirm my understanding is correct. If I use Single instance mode for a service:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
and this service calls a class from another asssembly which has a static constructor, that constructor is only called the first time ther service is called? The constructor I am talking about sets up a fair number of AutoMapper maps, and I only want this overhead the first time the service is called.
Taking this further, If I have two different services, and they both us the shared class, am I correct that the static constructor is still only called once?
Best
Ray
There is no connection between InstanceContextMode and how many times static constructor is fired. Static constructor is called once per Application Domain. So if your services are hosted within one Application Domain then your constructor will be called once.
As far as I understand you use the contructor to register AutoMapper configuration... To me it is not a good approach. Assuming your services are hosted on IIS you would better create a Global.asax file and then run you mapping registration code in Application_Start method. Of cource you can wrap it in some static method first.
Hope it helps!

Can a custom UserNamePasswordValidator add things to the WCF session?

Related to this question, I'm instantiating a connection to our internal API inside my custom UserNamePasswordValidator. Can I stash this somewhere so that I can use it in future calls in that user's session?
This is similar to this question, but I'm not using IIS, so I can't use HttpContext.Current (or can I?).
Update: Some context: our internal API is exposed via a COM object, which exposes a Login method. Rather than have a Login method in my service interface, I've got a custom UserNamePasswordValidator, which calls the Login method on the COM object.
Because instantiating the COM object and logging in is expensive, I'd like to re-use the now-logged-in COM object in my service methods.
Yes, it can. You'll need:
a custom ServiceCredentials implementation that returns a custom SecurityTokenManager.
a custom SecurityTokenManager implementation that returns a custom CustomUserNameSecurityTokenAuthenticator.
your custom CustomUserNameSecurityTokenAuthenticator needs to override ValidateUserNamePasswordCore, and should add a custom implementation of IAuthorizationPolicy.
your implementation of IAuthorizationPolicy should implement Evaluate, at which point it can start putting things in the WCF context.
replace the evaluationContext["PrimaryIdentity"] value with a PasswordIdentity or a custom IIdentity.
replace the evaluationContext["Principal"] value with a PasswordPrincipal or a custom IPrincipal.
update the evaluationContext["Identities"] collection to replace the GenericIdentity instance with your custom instance.
By doing this, you can have a custom IPrincipal implementation with some extra information in it.
For more details, see this.
UserNamePasswordValidator is absolutely out of all WCF contexts. It is only used to validate user name and password. Can you futher explain your problem?
Edit:
I guess COM object is instantiated for each session, isn't it? Otherwise wrapping COM into singleton should solve your problem. If you need to have per session COM object shared between validator and service instance you will need some cache or registry - something which is outside both validator and service and can be called from both of them.

NHibernate Session gets disposed off on each wcf service method call

I am using Wcf in Sharp Architecture. I have configured my project following northwind sample using WcfSessionStorage etc. I have a method in the wcf service that gets a list of business object using Repository<>.GetAll(). I am testing the service method using WcfTestClient. When the method is called the very first time, everything works fine. However on the subsequent call, I get the following exception on the Repository<>.GetAll() method
[System.ObjectDisposedException]
Session is closed!
Object name: 'ISession'
It seems like the NHibernate session gets disposed after each call. I have got around this problem by decorating my service with the following attribute
[ServiceBehavior( InstanceContextMode = InstanceContextMode.PerCall )]
public class WcfService : IWcfService
{
}
However this means, an instance of the service will be created on each call that in turn will create a new nhibernate session etc. In my scenario there is no need of creating a new service instance per call and I think its an expensive process and not the right solution. I would like to know what is the best practice in my scenario and how to get this thing work with creating a new service instace per call.
Thanks
Nabeel
The easiest way is to create a new instance every time and it's not an expensive process, because creating a new object in .NET is like 0.00000000000000001 second (I read that on Ayande's blog or somewhere).
I use Autofac DI in my projects and I usually make ISession as container scoped (one per request). And then every class that uses (directly or indirectly) ISession has to be container scoped or lower (factory scoped == every class usage get's a new instance). If a class that uses ISession is higer scoped (session scoped == singleton) you'll run into problems that you currently have.
If your service is singleton service:
At first run the service is created, this service uses ISession, which should be container scoped, and it is on the first run.
The next request to service (service is now created) has still a reference to created ISession (which was closed on previous end request), so now it's closed.
I don't recomend using the same ISession that you'll open/close (it's not recomended in the NHibernate documentation), just use container scoped (I do and I don't have any performance issues), or you should create ISession manually in every method in your service like:
using(ISession s = ISessionFactory.OpenSession())
using(ITransaction t = .....)
....
But that isn't nice at all...
Please take a look at my answer to my own similar question: WCF/S#arpArch: underlying ISession is closed after the first call within a request.
#dmonlord is right that the creation of additional session instances within the same request is very cheap in this case.

How do I initialize a Service Object when Self-Hosting in WCF

I am hosting a service within a Windows Service.
The following snippet instantiates the ServiceHost object:
Host = new ServiceHost(typeof(Services.DocumentInfoService));
The DocumentInfoService class implements a contract interface that has methods that invoke business objects requiring initialization (actually a connection string). Ideally, I'd like the hosting process to get the connection string from the config file and pass it to a constructor for my service object, DocumentInfoService, which would hold onto it and use it to pass to business objects as needed.
However, the ServiceHost constructor takes a System.Type object -- so instances of DocumentInfoService are created via the default constructor. I did note that there is another constructor method for ServiceHost that takes an object instance -- but the docs indicate that is for use with singletons.
Is there a way for me to get to my object after it is constructed so that I can pass it some initialization data?
ServiceHost will create the service instances based on the binding and behaviors configured for the endpoint. There's no particular point in time, where you can rely there is a service instance. Hence, ServiceHost does not expose the service instances.
What you could do is add code to your service object constructor to read the relevant configuration values itself through the ConfigurationManager class.
Of course, if you don't keep your configuration in the app.config, that won't work for you. Alternative approach would be to have a well-known singleton object that the service instances access when created to get the necessary configuration.
And there's also the option of creating your own ServiceHost or your own ServiceHostFactory to control the service instantiation explicitly. This would give you acess to the new service instances at the moment of creation. I would stay away from that option though. It's not worth the effort for your scenario.
Implement your own ServiceHost. See also http://hyperthink.net/blog/servicehostfactory-vs-servicehostfactorybase/