I am using the WCF REST stater kit to build a plain xml over HTTP service. As part of this Im using a RequestInterceptor to do authentication. Inside of the RequestInterceptor I have access to a System.ServiceModel.Channels.RequestContext object from which i can get the request url, querystring params and other helpful things. What I cannot work out is how to get access to the HttpContext of the request. I have several things stored in the HttpContext which I want to access inside the requestInterceptor but Im struggling to get to them. When I use the quickwatch inside Visual Studio I can see that it is there buried inside private members of the requestContext. Can somebody show me how to access the HttpContext, perhaps using reflection on the RequestContext object?
You can access ASP.NET's HttpContext inside any WCF service hosted in ASP.NET as long as you turn on compatibility. This is done in two steps:
Apply the AspNetCompatibilityRequirementsAttribute to your service class and set the RequirementsMode property to Required
Make sure you enable compatibility by configuring the following:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled=”true” />
</system.serviceModel>
Once you've done that, you can access the current HttpContext instance at any time using the static Current property. For example:
foreach(HttpCookie cookie in HttpContext.Current.Request.Cookies)
{
/* ... */
}
Note that enabling integration with the ASP.NET runtime does incur some additional overhead for each request, so if you don't need it you can save some performance by not enabling it and just using the System.ServiceModel.Web runtime instead. You have access to pretty much all the information you need using the HttpRequestResponseMessageProperty and HttpResponseMessageProperty classes.
For more information on the subject, see this section of MSDN titled WCF and ASP.NET.
Related
I have the unfortunate task of updating a WCF project to .NET Framework 4.8 and replacing the existing log4net exception handling with Microsoft Logging and Application Insights.
My approach was to implement Dependency Injection to make instantiation easier and because I am already used to that design approach with .NET Core. As you may know, WCF services adds its own complexity since WCF is responsible for instantiating the services and lower level objects (like custom customUserNamePasswordValidatorType). I was able to handle most of this by implementing a WCF Service Factory and updating the svc markup with it.
I have added Application Insights to the project via the appropriate NuGet packages which updates the web.config with appropriate httpModules for general exception handling. I was even able to add a custom TelemetryInitializer in Application_Start to include a few custom properties in the message.
My problem is getting an instance of ILogger<T> with the attached Application Insights provider into the instantiated service.
At first, I was getting an exception because of the parameterless constructor of Logger<T>. This was fixed by updating my WcfServiceFactory to the following
container
...
.RegisterType<ILoggerFactory, LoggerFactory>(TypeLifetime.Singleton)
.RegisterType(typeof(ILogger<>), typeof(Logger<>), TypeLifetime.Singleton);
This allowed an instance of the logger to be passed into the constructor of each service. However, calls to log messages are never written to App Insights and an inspection of the logger shows zero providers.
My guess is that because a new instance of LoggerFactory is being created, the already existing instance used in the httpModules is ignored.
According to https://github.com/unitycontainer/microsoft-logging, I need to refactor what I am doing and actually create an instance of a LoggerFactory and manually add the desired providers. My issue is that I cannot figure out how to do that with Application Insights. Everywhere else I used it, I would just call the AddApplicationInsights() extension method but that does not seem to be an option here (at least not with Unity).
So I guess my issue boils down to the following questions
Can I get the WcfServiceFactory to use the existing App Insights logging? Maybe establish something in Global.asx?
How can I manually register App Insights as a provider in the WcfServiceFactory including the custom telemetry?
No need to use ILogger if the intention is just to log a custom error. You can log exception on AppInsights directly using the telemetry client, like this:
var telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
telemetryClient.TrackException(new Exception("Logged random exception message."));
Hello i have an application on which i am doing a custom authentication on the server side.
Now i need to port this logic to a Blazor Client.I do not know how i can access HttpContext data such as:
HttpContext.Request.Host.Value
HttpContext.User.Identity.IsAuthenticated
and also how to use the extension method Microsoft.AspNetCore.Authentication.SignInAsync extension method.
How can i get the HttpContext from the client ?
Sending the HttpContext object to the client-side Blazor is a bad idea. HttpContext Accessor is used to inject the HttpContext into classes that have no direct access to the HttpContext object. If you still want to do it, see comment by # Flores.
I'm not sure what custom authentication system you want to create, but I'd suggest you learn first how to do that the Blazor way. See comment by #dani herrera for a sample by the Blazor team. This sample will also give you the idea of what data you should pass to the client-side Blazor. Of course you can extend this authentication system in many ways: Jwt authentication can be a good exercise for you in extending the Blazor Auth System.
I'm writing a client to access a SOAP webservice, that will be hosted by a third party. I have the WSDL and XSD that define the interface and the data.
I've had no problem in creating a service reference from the WSDL, but I'm having a problem in building a simple web service that implements it, that I can use to test against. (The third party's service isn't ready, yet, but even were it running, I'd still like to do my initial testing against my own test server, not against theirs.)
I've browsed around, and apparently I can use svcutil to generate an interface for the service:
svcutil.exe thewsdl.wsdl thexsd.xsd /language:c# /out:ITestService.cs
This generates a file containing the service interface definition. But now what?
I figured the easiest way to go would be to build a self-hosted service, so I created a new console app, and in it I implemented a class derived from the service interface definition, and fired it up with a ServiceHost.
It runs, and while it was running I was able to create a Service Reference in my client app. But when I try to call it, from the client app, I get an error:
The provided URI scheme 'http' is invalid; expected 'https'.
What is the easiest way to get around this? Is there a simple way to simply turn off authentication and authorization, and simply allow unrestricted access?
EDITED:
I'm adding a bounty to this, as the original question seems to have attracted no attention.
But let's get to the crux. I am trying to write a client against a customer's SOAP service. As a part of the development, I want to create my own test WCF service, that implements the same WSDL.
So I have a downloaded .wsdl file, and an associated .xsd file, and with them I want to create a service that I can test against, with VS2010's debugger.
It's not important to me whether this service runs standalone, or within IIS, or that it be production stable. All I want is a service that accepts the requests that the customer's site would accept, and return the responses to my client that I need it to return, in order to test my handling of them.
How do I get there? I've tried adding a WCF Service Library, and then using svcutil.exe within it to add my new service, but it doesn't seem to populate the app.config with the server-side boilerplate, and my attempts to reconstruct it haven't worked.
Since you want a full fledged service to call instead of mocking it.
Follow these steps:
Create new "WCF Service Application" project
Copy wsdl and xsd into project
select your wsdl file and look in the properties section and copy location from full path
Right click on the project in solution explorer and select "Add Service Reference..."
For the service address, paste the location of your wsdl that was copied in previous step and hit go. It should show the operations you are expecting for the service.
hit ok
It should generate all the objects for you including the interface and config file (although at this point is client side in the config- we will have to switch this to be the service)
Now you should add the service config section in the system.serviceModel section. Since I don't know the specifics of your wsdl what you should do is create the services node inside the system.serviceModel section and copy the endpoint node from the client node generated. For example below of services node, you can blank out the address for now:
<system.serviceModel>
<services>
<service name="YourService">
<endpoint address=""
binding="basicHttpBinding" bindingConfiguration="WeatherSoap"
contract="ServiceReference1.WeatherSoap" name="WeatherSoap" />
</service>
delete the client node in the config
In the service, it is implementing a different interface when it generated the project so you will want to replace the interface implemented with the one listed in the contract attribute in the endpoint above. Then implement its members and it should explode out the operations available. You can fill in whatever you want the service operations to return.
depending on what the wsdl has in it, we may need to do a few more things to allow the necessary bindings to run - like setting up for wsHttpbinding, netTCPbinding, etc.
I've used Moq to handle this. Basically in the unit tests you specify the interface (this would have been generated for you with adding the service reference or using svcutil) and what you want it to return if you call it.
example setup below:
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
So then when you want to moq out your service call
var myObject = new IFoo;
var resp = myObject.DoSomething("whateverwillbeoverriddenbyping");
and resp will be true.
There are other options than using Moq. The options all involve taking the interface and injecting a different version of it. For example, you could also do a constructor injection mock, by passing in the interface to your class constructor.
I am trying to consume a WCF web service from a .NET client application, and I think I need to be able to programmatically create endpoints, but I don't know how. I think I need to do this because, when I try to run the application, I am getting the following error:
Could not find default endpoint
element that references contract
'IEmailService' in the ServiceModel
client configuration section. This
might be because no configuration file
was found for your application, or
because no endpoint element matching
this contract could be found in the
client element.
While troubleshooting this error, I created a simple windows forms application, in which I try to consume the same web service. With this test application I can connect to the web service successfully, and I get a valid response. But, I can reproduce the exact error cited above within in my test app by removing the system.serviceModel node and all of its child nodes from the application's app.config file (I might not have to remove ALL of that section, I'm not sure). So, my first thought was that I need to add that section to the app.config file for the real app, and everything should be fine. Unfortunately, for ridiculous reasons that I won't get into here, that is not an option. So, I am left with having to generate this information in code, inside the client app.
I am hoping someone here can help me work through this, or can point me toward a good resource for this sort of problem.
Is it possible to create endpoint configurations in the client app, in code?
By default, when you do an Add Service Reference operation, the WCF runtime will generate the client-side proxy for you.
The simplest way to use it is to instantiate the client proxy with a constructor that takes no parameters, and just grab the info from the app.config:
YourServiceClient proxy = new YourServiceClient();
This requires the config file to have a <client> entry with your service contract - if not, you'll get the error you have.
But the client side proxy class generated by the WCF runtime also has additional constructors - one takes an endpoint address and a binding, for instance:
BasicHttpBinding binding = new BasicHttpBinding(SecurityMode.None);
EndpointAddress epa = new EndpointAddress("http://localhost:8282/basic");
YourServiceClient proxy = new YourServiceClient(binding, epa);
With this setup, no config file at all is needed - you're defining everything in code. Of course, you can also set just about any other properties of your binding and/or endpoint here in code.
An east way to consume a WCF service if you have a reference to the assembly which defines the interface, is using the System.ServiceModel.ChannelFactory class.
For example, if you would like to use BasicHttpBinding:
var emailService = ChannelFactory<IEmailService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(new Uri("http://some-uri-here.com/));
If you don't have a reference to the service assembly, then you can use one of the overloaded constructors on the generated proxy class to specify binding settings.
So I already have a working implementation of StructureMap with the WCF service (including custom instance provider, behaviors, etc.)
When I try to have an object that is instantiated only once per user request, I use the InstanceScope.HttpContext and it throws because the context is null.
Do anyone have a proper way of doing that?
On the server-side of the WCF service? By default, WCF has nothing to do with ASP.NET and thus all your HttpContext etc. aren't there.
By default, your WCF services will be called on a "per-call" basis, e.g. each request gets a brand-new, separate, totally isolated instance of your service class. Why not just put those things into the service class as internal fields??
Or you might want to check out this blog post on how to abstract request state and providing sample implementations for ASP.NET (using HttpContext.Items) and WCF.