Enable HTTP context in WCF service - wcf

i added
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
but it's giving me an error"
The service cannot be activated because it requires ASP.NET compatibility. ASP.NET compatibility is not enabled for this application
it seems like the WCF service has no HTTP context related to it? please help

It has check out the following link
http://msdn.microsoft.com/en-us/library/aa702682.aspx
and make sure you have added this tag in your web config

Related

SharePoint 2010 hosted wcf and castle windsor

I am trying to work out how to host a wcf service in sharepoint 2010 which uses castle windsor. I can host my own standard custom web service without any issues by using one of the service factories from http://msdn.microsoft.com/en-us/library/ff521586(v=office.14).aspx.
Setting up a normal wcf service with castle windsor involves modifying the global.asax but, as this is not recommended for SharePoint, I have created an HttpModule which sets up the container and I have updated the web config to use it by creating a feature reciever.
My problem is where to go next. I am using the MultipleBaseAddressBasicHttpBindingServiceHostFactory for my service because that dynamically configures all of the endpoints for the service based on the IIS configuration but in order to use castle windsor it looks like it is necessary to change to using the supplied Castle.Facilities.WcfIntegration.WindsorServiceHostFactory. I have tried just switching over to see what happens but that does not seem to work. I get the following error
Error: Cannot obtain Metadata from <svc url> If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: <svcurl> Metadata contains a reference that cannot be resolved: '<svcurl>'. The requested service, '<svcurl>' could not be activated. See the server's diagnostic trace logs for more information.HTTP GET Error URI: <svcurl> There was an error downloading '<svcurl>'. The request failed with HTTP status 404: Not Found.
I assume this is because I haven't configured an endpoint for the service but the few examples I have seen online do not seem to either.
Has anyone managed to get castle windsor and sharepoint wcf working - preferably with dynamic configuration if possible?
The error message that you are getting is that the metadata of the service is not published. To do this you need 2 things:
A mex endpoint for your service:
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
And service meta data turned on in service behavior:
<serviceMetadata httpGetEnabled="True" />

How to access HttpContext.Current.User.Username in WCF service

How can I access HttpContext.Current.User.Username from a web application in a WCF service?
Generally you don't - HttpContext is an ASP.NET concept and doesn't apply to WCF unless you run it with ASP.NET Compatibility turned on.
If you want the current user in WCF then use ServiceSecurityContext.Current.PrimaryIdentity or get the security context via the OperationContext.
Actually, with Asp.Net Compatibility mode on, you can access HttpContext.Current.User from a WCF service hosted in the site. See Microsoft's site for details: https://msdn.microsoft.com/en-us/library/aa702682(v=vs.110).aspx
If your service is hosted in an Asp.net site you just need to update your web.config to set aspNetCompatibilityEnabled="true" on the serviceHostingEnvironment element:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>

Custom binding element can't be loaded in WCF under IIS, however it can load under WCF Self-Host

I'm able to run the WCF-SecureProfile sample that comes with the MSFT WCF samples download (http://msdn.microsoft.com/en-us/library/ee818238.aspx)
However I can't port this server component to IIS. I get the error that
<MakeConnectionBindingElement/> can't be loaded. Considering that I have the behavior extensions loaded I don't know why IIS can't see the extension, however the self-host version of my app can.
I uploaded the sourcecode of the project into codeplex for easy browsing. Here is a direct link to web.config and all other files.
2
I got the sample and set it up to run on IIS local. I didn't get the same issue as the one in this question but I did run into a big gotcha. Accessing the service in IIS gave me this error message:
Contract requires Duplex, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it.
After some head scratching, I found the cause of this issue. WCF 4 now assigns default bindings to each transport (I'm liking this feature less & less). For the HTTP transport, the default binding is basicHttpBinding. The problem is the customBinding config does not override any default binding. This causes WCF to attempt to configure duplex over basicHttpBinding which of course isn't supported. The fix is to turn off the default transport mapping for HTTP and assign it to your custom binding as shown below for this service:
<protocolMapping>
<clear/> <!-- removes all defaults which you may or may not want. -->
<!-- If not, use <remove scheme="http" /> -->
<add scheme="http" binding="customBinding" bindingConfiguration="rspBinding"/>
</protocolMapping>
Once I added this to the serviceModel element, the IIS based service worked just fine.

How to get working path of a wcf application?

I want to get the working folder of a WCF application. How can I get it?
If I try
HttpContext.Current.Request.MapPath(HttpContext.Current.Request.ApplicationPath)
I get a null reference exception (the Http.Current object is null).
What I meant with the working folder was the folder where my WCF service is running. If I set aspNetCompatibilityEnabled="true", I get this error:
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
I needed the same information for my IIS6 hosted WCF application and I found that this worked for me:
string apPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
As always, YMMV.
Please see ongle's answer below. It is much better than this one.
Updated after more information
The following worked for me. I tested it with a new WCF Service I hosted on IIS through a Service1.svc.
Add <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> to web config. <system.serviceModel>..</ ..> existed already.
Add AspNetCompatibilityRequirementsAttribute to the service with Mode Allowed.
Use HttpContext.Current.Server.MapPath("."); to get the root directory.
Below is the full code for the service class. I made no changes in the IService1 interface.
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public void DoWork()
{
HttpContext.Current.Server.MapPath(".");
}
}
And below is an excerpt from the web.config.
<system.serviceModel>
<!-- Added only the one line below -->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<!-- Everything else was left intact -->
<behaviors>
<!-- ... -->
</behaviors>
<services>
<!-- ... -->
</services>
</system.serviceModel>
Old answer
What do you mean by the Working Folder? WCF services can be hosted in several different ways and with different endpoints so working folder is slightly ambiguous.
You can retrieve the normal "Working folder" with a call to Directory.GetCurrentDirectory().
HttpContext is an ASP.Net object. Even if WCF can be hosted on IIS, it's still not ASP.Net and for that reason most of the ASP.Net techniques do not work by default. OperationContext is the WCF's equivalent of HttpContext. The OperationContext contains information on the incoming request, outgoing response among other things.
Though the easiest way might be to run the service in ASP.Net compatibility mode by toggling it in the web.config. This should give you access to the ASP.Net HttpContext. It will limit you to the *HttpBindings and IIS hosting though. To toggle the compatibility mode, add the following to the web.config.
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>
Depending on what you want. I usually want to resolve a url like "~/folder/file". This is what worked.
System.Web.Hosting.HostingEnvironment.MapPath("~/folder/file");
More general, I am using this one
AppDomain.CurrentDomain.BaseDirectory
The aspNetCompatibilityEnabled="true" should have resolved my problem, but I got this error:
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
I resolved my problem with getting the physical path of my running WCF service by getting it from my current app domain:
AppDomain.CurrentDomain.BaseDirectory
In order to reference ASP.NET features like the HttpContext object, you need to run your WCF app in ASP.NET compatibility mode. This article explains how to do this.
Use HostingEnvironment.ApplicationPhysicalPath in WCF to find your application physical path.
Use namespace
using System.Web.Hosting;

404 BadRequest exposing WCF service through external IP using IIS host headers

We host a WCF webservice on Windows Server 2003. This server only has 2 internal IP's. We want to expose the service externally. This is done through the firewall that maps an external IP to the service.
So, I would need to modify the service to display that external IP for the internal links. This is not an issue since it should only be used externally.
Changing the Host Header value in IIS gives a 'Bad Request (Invalid Hostname)' response from IIS. I also added an 'address' value to the endpoint entry in the web.config ... but it sill just points to the internal machine name. Any ideas?
edit: I can verify that IIS7 has the exact same behaviour. Address didn't work. Different hostname gave Invalid Hostname error. Is there seriously no way to present a different (fictive) IP? :/
edit2:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicAnonymous">
<security mode="None"/>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Extended">
<serviceMetadata httpGetEnabled="true"/>
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
</behavior>
</serviceBehaviors>
</behaviors>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="false" logMessagesAtServiceLevel="false" logMessagesAtTransportLevel="true" maxMessagesToLog="3000"/>
</diagnostics>
<services>
<service behaviorConfiguration="Extended" name="AnCWCFWebService.ProductInfoProvider">
<endpoint address="" binding="basicHttpBinding" name="ASMX" bindingConfiguration="BasicAnonymous" contract="AnCWCFWebService.Interfaces.IProductInfoProvider"/>
</service>
</services>
</system.serviceModel>
404 BadRequest Due to IIS Configuration...
If you are receiving a 404 BadRequest error from IIS after attempting to modify host headers in IIS, this is common, but there is a fix!
Fix By Making IIS Configuration Changes
How can WCF support multiple IIS Binding specified per site?
Fix By Making WCF Code Modifications
Alternatively, the following article explains how one developer solved this issue with a combination of configuration and code:
Well, that was fun! An adventure in WCF, SSL, and Host Headers
http://geekswithblogs.net/rakker/archive/2008/07/03/123562.aspx
The article references two important links...
The first one explains how to properly set the host headers in IIS:
Configuring Server Bindings for SSL Host Headers (IIS 6.0): http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/8d9f2a8f-cd23-448c-b2c7-f4e87b9e2d2c.mspx?mfr=true
After getting host headers working, you'll find that...
"you can't have more than one host
header for IIS or wcf will break"
The solution to working around this limitation is found within this article, and there is also a comment on the GeeksWithBlogs.net article above that provides an enhanced variation:
WCF: This collection already contains
an address with scheme http
If you are still experiencing trouble, let us know in the comments below...
If the Service is Not Working...
My experience with WCF is that it is very tricky at times, especially with configuration. If one is following best practices and not doing anything non-standard, the great majority of deployment problems are the result of a botched configuration file.
In theory (not so much in practice, due to architectural differences), setting up a WCF service on IIS should be no different than setting up a typical virtual directory and corresponding application for web application or for an ASMX web service.
Therefore, I recommend that if this is the first WCF service you are exposing to the Internet, follow the same simple approach you would take when exposing your first website. Basically, create a new sample "WCF Service Application" (this is available in the Add New Project dialog, under the Web section of C# or VB).
Once you have it working, follow your deployment practices to move it into a production sandbox and test it locally. This sandbox would preferably already have some web sites or web services installed and known to be accessible from the Internet, in order to eliminate any doubt about the typical network configuration issues. If you have a sample ASMX web service that is already successfully exposed on the Internet from that server, that would be best.
Next, try testing the the ASMX and the WCF services from web browser, both locally on the server, internally on other desktops and then finally externally.
Testing URLs
We want to test accessing the standard SVC and ASMX file from the web browser in all the varieties of URL flavors that are available and relevant. The results should be similar, with summary page about he service rendering in the window. The difference will be that the ASMX web service's summary will likely allow you to execute the web methods on the service if that feature has not been disabled in the web.config file.
Compare the results of browser fetches of the following styles of URLs...
http://localhost/WcfService1/Service1.svc
http://localhost/WcfService1/Service1.asmx
http://MachineName or MachineFQN/WcfService1/Service1.svc
http://MachineName or MachineFQN/WcfService1/Service1.asmx
http://MachineLocalIP#1/WcfService1/Service1.svc
http://MachineLocalIP#1/WcfService1/Service1.asmx
http://MachineLocalIP#2/WcfService1/Service1.svc
http://MachineLocalIP#2/WcfService1/Service1.asmx
http://ExternalIP/WcfService1/Service1.svc
http://ExternalIP/WcfService1/Service1.asmx
All of these tests should return similar results.
Testing Service Methods
If you feel like it, go head and test some web methods on the ASMX web service for any of the tested URLs, from the web browser. You'll soon see that we can test ASMX web services a different way also...
Next we'll test web methods on both the WCF service and the ASMX web service by using the WcfTestClient.exe application that is found in the Visual Studio 2008 distribution (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE).
You will need to add the services through the File->Add Service menu item, typing in the URL above for each service URL that you wish to test. Make sure to include the filename of the SVC and ASMX files. If all is well, the MEX endpoint that is enabled by the "httpGetEnabled" attribute of the <serviceMetadata/> element in the web.config file will return the data that is necessary for the utility to operate, thereby populating the tree with the inventory of our service methods like this:
From this point, it will be useful to refer to the following to resources:
WCFTestClient: http://msdn.microsoft.com/en-us/library/bb552364.aspx
What's New for WCF in Visual Studio 2008: http://msdn.microsoft.com/en-us/magazine/cc163289.aspx
Conclusion
If you make it this far, then I do not expect any other issues and you should now attempt to compare the setup of the samples to the WCF service that you are attempting to publish to the Internet, and hopefully the differences will be obvious.
Remember to treat the WCF service like an ASMX web service during you diagnostics, assuming that the web.config is known to be set up correctly.
If you are still unable to make things work, check this guide for further technical advice:
Deploying an IIS-hosted WCF service: http://msdn.microsoft.com/en-us/library/aa751792.aspx
Finally, if all else fails, just wrap your WCF service in an ASMX web service:
How to: Expose WCF service also as ASMX web-service: http://kjellsj.blogspot.com/2006/12/how-to-expose-wcf-service-also-as-asmx.html
You just need to configure your host header in the IIS so that the links in the WSDL references will use the donmain name rather local machine name.
Check out
Steps to configure IIS host header so that WCF will use domain name in WSDL references.
Why not just assign a new IP address to the server instead of messing around with hostnames? A Windows Server can have multiple IP addresses for the same NIC.
Here is an article that talks about it.