REST methods not accessible when hosting wcf service in IIS - wcf

I have a WCF REST service that exposes a method in class GreetService:
[ServiceContract]
public class GreetService
{
[WebGet(UriTemplate = "greet/{name}")]
public String GreetName(string name)
{
return "Hello " + name;
}
}
Also, I registered a route in Global.asax:
RouteTable.Routes.Add(new ServiceRoute("GreetService", new WebServiceHostFactory(), typeof(GreetService)));
Now when i run this directly from visual studio, I am able to leverage the UriTemplate and invoke this method using a GET call to
http://localhost:5432/GreetService/greet/JohnDoe
However, after deploying this to IIS7 by creating a Greet.svc file for it, I am observing the following behavior:
I can call http://localhost:5432/Greet.svc and it says that a service has been created
I can point wcftestclient to http://localhost:5432/Greet.svc?wsdl to generate a test client which can call GreetName() directly
However, I can't call http://localhost:5432/Greet.svc/GreetService/greet/JohnDoe nor http://localhost:5432/Greet.svc/greet/JohnDoe although I expected to be able to since I specified an empty relative endpoint address in the corresponding web.config file prior to hosting it in IIS7.
Any ideas why the WebGetAttribute is not working in IIS? Or is there something else I am doing wrong?
EDIT:
This is the ServiceModel part of my web.config file which resides in the directory that IIS uses:
<system.serviceModel>
<!-- <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> -->
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
EDIT 2: For completeness' sake here is my full web.config file:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule"
type="System.Web.Routing.UrlRoutingModule,
System.Web, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
<handlers>
<add name="UrlRoutingHandler"
preCondition="integratedMode"
verb="*" path="UrlRouting.axd"
type="System.Web.HttpForbiddenHandler,
System.Web, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
</system.webServer>
<system.serviceModel>
<!--<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>-->
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
</configuration>

If you've defined your route to be:
new ServiceRoute("GreetService", .....
then you should be able to call your service at
http://localhost:5432/YourVirtualDirectory/GreetService/greet/JohnDoe
and if your web app is deployed to your IIS root (not in a virtual directory), that would be:
http://localhost:5432/GreetService/greet/JohnDoe
When defining a ServiceRoute, that's done to get rid of having to specify the Greet.svc file, really - the ServiceRoute entry already contains all the information IIS needs to instantiate your service and call it - no need for having the *.svc file involved in your URL (the svc file basically contains the same info your ServiceRoute entry has).

Change the line in your global.asax.cs to read:
RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(GreetService)));
and put the following in your web.config right under the root <configuration> node:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule"
type="System.Web.Routing.UrlRoutingModule,
System.Web.Routing, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
</modules>
<handlers>
<add name="UrlRoutingHandler"
preCondition="integratedMode"
verb="*" path="UrlRouting.axd"
type="System.Web.HttpForbiddenHandler,
System.Web, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
</system.webServer>
(do make sure you're using the right .NET version) and see what that does for you.

NOTE: please post the web.config, at least the system.servicemodel part.
You normally use either the Route-based configuration or a .svc file, not both, but that's orthogonal to your problem. FWIW, you should be able to kill the .svc file once you get the service working and just use the route.
Since you're able to generate WSDL and call it, that sounds like you might not have webhttp as an endpoint behavior?
Make sure you have an endpoint behavior defined like this (can be a diff name of course)
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
and then make sure your service endpoint includes behaviorConfiguration="webHttpBehavior"

The problem is machine config missing the following section
<configSections>
<sectionGroup name="system.serviceModel" type="System.ServiceModel.Configuration.ServiceModelSectionGroup, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="standardEndpoints" type="System.ServiceModel.Configuration.StandardEndpointsSection, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</sectionGroup>
</configSections>
Add it on top of web.config (after the opening tag of <configuration> ) should fix this problem.

Related

Web.config jsonSerialization maxJsonLength ignored

I have an MVC3 application running under .NET 4.0 and when I use JavascriptSerializer.Deserialize I'm getting an error.
Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.
Reading Can I set an unlimited length for maxJsonLength in web.config I put the jsonSerialization maxJsonLength key in my web.config but it gets ignored. Though I can set the JavaScriptSerializer.MaxJsonLength property in code and it works fine.
I would like to have the value in the Web.config rather than code. Here is how I am using JavaScriptSerializer.
Dim client As New WebClient
...
Dim result = _client.DownloadString("Test")
Dim serializer = New JavaScriptSerializer
Return serializer.Deserialize(Of Foo)(result)
Here is my Web.config
<configuration>
<configSections>
...
</configSections>
<appSettings>
...
</appSettings>
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="/Http404"/>
<error statusCode="403" redirect="/Http403"/>
<error statusCode="550" redirect="/Http550"/>
</customErrors>
<compilation debug="true" targetFramework="4.0"/>
<pages controlRenderingCompatibilityVersion="4.0">
<namespaces>
<add namespace="System.Web.Helpers"/>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Web.WebPages"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="50000000"/>
</webServices>
</scripting>
</system.web.extensions>
<system.webServer>
....
</system.webServer>
</configuration>
According to the link you provided (the 2nd most voted answer), your web.config setting will be ignored because you're using an internal instance of the JavaScriptSerializer.
If you need the value to be stored in the web.config, you could add a key in the <appSettings> section called maxJsonLength with a value of 50000000 and then in your code, you could use it like:
var serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = ConfigurationManager.AppSettings['maxJsonLength'];

Running ServiceStack side by side with MVC

I managed to run ServiceStack side by side with MVC4, but I still have a little problem and hope someone can help me with that.
When executing a debugging session through VS2012, everthying works perfect - the browser is opened and the first page is loaded well. But then when refreshing the page, and trying to get to http://localhost:62322/Content/site.css, the following error is displayed:
Handler for Request not found:
Request.ApplicationPath: /
Request.CurrentExecutionFilePath: /Content/site.css
Request.FilePath: /Content/site.css
Request.HttpMethod: GET
Request.MapPath('~'): D:\All\Projects\ExampleProject\trunk\ExampleProject\ExampleProject\
Request.Path: /Content/site.css
Request.PathInfo:
Request.ResolvedPathInfo: /Content/site.css
Request.PhysicalPath: D:\All\Projects\ExampleProject\trunk\ExampleProject\ExampleProject\Content\site.css
Request.PhysicalApplicationPath: D:\All\Projects\ExampleProject\trunk\ExampleProject\ExampleProject\
Request.QueryString:
Request.RawUrl: /Content/site.css
Request.Url.AbsoluteUri: http://localhost:62322/Content/site.css
Request.Url.AbsolutePath: /Content/site.css
Request.Url.Fragment:
Request.Url.Host: localhost
Request.Url.LocalPath: /Content/site.css
Request.Url.Port: 62322
Request.Url.Query:
Request.Url.Scheme: http
Request.Url.Segments: System.String[]
App.IsIntegratedPipeline: False
App.WebHostPhysicalPath: D:\All\Projects\ExampleProject\trunk\ExampleProject\ExampleProject
App.DefaultHandler: DefaultHttpHandler
App.DebugLastHandlerArgs: GET|/Content/site.css|D:\All\Projects\ExampleProject\trunk\ExampleProject\ExampleProject\Content\site.css
But if I delete the following line of code in AppHost.cs, everything works well, and the handler for site.css is always found:
SetConfig(new EndpointHostConfig { ServiceStackHandlerFactoryPath = "api", DefaultContentType = ContentType.Json });
My requirements for the project are wrapping with ServiceStack any call through the browser (all controllers) as well as calls to /api, which should be handled by a ServiceStack service.
I followed the instructions here:
https://github.com/ServiceStack/ServiceStack/wiki/Run-servicestack-side-by-side-with-another-web-framework
and my web.config looks like this:
<system.web>
<!--...-->
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
<!--...-->
</system.web>
<location path="api">
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
</location>
Does anybody know why the handler for site.css sometimes found and sometimes not?
Furthermore, if I did a mistake with configuring ServiceStack to wrap my whole server, please point me to them.
From what you are trying to do I would recommend starting with a plain ASP.NET Web Application. Once your project is set, using NuGet you could do
Install-Package ServiceStack.Host.AspNet
or just follow the configuration here. Doing this runs ServiceStack at the root path /.
In your set up above you don't need this line...
SetConfig(new EndpointHostConfig { ServiceStackHandlerFactoryPath = "api", DefaultContentType = ContentType.Json });
Adding it is telling ServiceStack to only handle requests that contain the '/api' path which is not what you want.

Windows Service Bus 1.0, Appfabric, Netmessagingbinding failuring

I seem to run into the same problem over and over again when I am trying to host a WCF service in Windows Server AppFabric that uses netmessagingbinding to receive messages from Windows Service Bus 1.0 queues. AppFabric aborts the service, so if I press F5 on service?wsdl then I sometimes get failures, sometimes I get a nice WSDL generated. Where is my mistake? It is rather impossible to find an example that uses AppFabric, netmessagingbinding and Windows Service Bus (not Azure), so I haven't been able to finde my mistake...
[ServiceContract]
public interface ISBMessageService
{
[OperationContract(IsOneWay = true, Action = "DoSomething")]
[ReceiveContextEnabled(ManualControl = true)]
void DoSomething(string something);
}
[ServiceBehavior]
public class SBMessageService : ISBMessageService
{
[OperationBehavior]
public void DoSomething(string something)
{
Trace.WriteLine(String.Format("You sent {0}", something));
// Get the BrokeredMessageProperty from the current OperationContext
var incomingProperties = OperationContext.Current.IncomingMessageProperties;
var property = incomingProperties[BrokeredMessageProperty.Name] as BrokeredMessageProperty;
ReceiveContext receiveContext;
if (ReceiveContext.TryGet(incomingProperties, out receiveContext))
{
receiveContext.Complete(TimeSpan.FromSeconds(10.0d));
}
else
{
throw new InvalidOperationException("...");
}
}
}
<?xml version="1.0"?>
<configuration>
<appSettings>
<!-- Service Bus specific app setings for messaging connections -->
<add key="Microsoft.ServiceBus.ConnectionString"
value="Endpoint=sb://LRNcomp/LRNnamespace"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<httpRuntime/>
</system.web>
<system.serviceModel>
<!-- These <extensions> will not be needed once our sdk is installed-->
<extensions>
<bindingElementExtensions>
<add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</bindingElementExtensions>
<bindingExtensions>
<add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</bindingExtensions>
<behaviorExtensions>
<add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" httpHelpPageEnabled="True"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="securityBehavior">
<transportClientEndpointBehavior>
<tokenProvider>
<sharedSecret issuerName="owner" issuerSecret="somthing"/>
</tokenProvider>
</transportClientEndpointBehavior>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<netMessagingBinding>
<binding name="messagingBinding" closeTimeout="00:03:00" openTimeout="00:03:00" receiveTimeout="00:03:00" sendTimeout="00:03:00" sessionIdleTimeout="00:01:00" prefetchCount="-1">
<transportSettings batchFlushInterval="00:00:01"/>
</binding>
</netMessagingBinding>
</bindings>
<services>
<service name="SBExamples.SBMessageService">
<endpoint name="Service1" address="sb://LRNcomp:9354/LRNnamespace/test/myqueue2" binding="netMessagingBinding" bindingConfiguration="messagingBinding" contract="SBExamples.ISBMessageService" behaviorConfiguration="securityBehavior"/>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
An error in the WCF contract generated many strange exceptions, like my transport channel was aborted. Proper sharing of contract between sender and receiver did the trick.

How to enable basic authentication on WCF 4.0 REST Service?

First of all there are plenty of articles on the net for this but most of them are for WCF 3.5. I'm using some features of WCF 4.0 which makes the scenario a bit different.
Following is my contract:
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate="x?v={value}")]
string GetData(int value);
}
Following is my service class:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
Following is my web.config
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
<handlers>
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd"/>
</handlers>
</system.webServer>
I'm not using any svc file so in Global.asax I've written the following line of code to expose my service at path 'blah'
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("blah", new WebServiceHostFactory(), typeof(Service1)));
}
Now for enabling basic authentication if I change standard endpoint in web.config as follows:
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint automaticFormatSelectionEnabled="true">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
I get the following error:
Could not find a base address that
matches scheme https for the endpoint
with binding WebHttpBinding.
Registered base address schemes are
[http].
What should I do from this point onwards to make it work? And where will I check the username/password supplied with each request?
This can't be tested in ASP.NET Development Server and for running in IIS 7.5 we have to install basic authentication and also we need to create a certificate and associate ssl binding with that application.
Doing all of that resulted in webservice methods to require basic authentication but it was working against AD.
There is no way to change it to authenticate it yourself.

Why does my WIF enabled WCF service throw exception when I try to host it?

Following the instructions here: http://msdn.microsoft.com/en-us/library/ee517277.aspx, I am trying to set up a WCF service to use WIF.
When I try to instantiate the ServiceHost, the following exception is thrown:
The type 'Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement' registered for extension 'federatedServiceHostConfiguration' could not be loaded.
I have never set up WCF service to use WIF before, but I have successfully set up web sites to use WIF. What could be causing this?
Module Module1
Sub Main()
Dim sh As ServiceModel.ServiceHost
''#Exception thrown on following line
sh = New ServiceModel.ServiceHost(GetType(testService))
Microsoft.IdentityModel.Tokens.FederatedServiceCredentials.ConfigureServiceHost(sh)
sh.Open()
Console.WriteLine("Service running")
Console.ReadLine()
sh.Abort()
End Sub
End Module
<?xml version="1.0" encoding="utf-8" ?>
<configuration><system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ClaimsBehavior" >
<federatedServiceHostConfiguration/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="ClaimsBehavior" name="WCFConsoleService.testService">
<endpoint address="net.tcp://localhost/testservice" binding="netTcpBinding"
bindingConfiguration="" contract="WCFConsoleService.iTestService" />
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="federatedServiceHostConfiguration"
type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement" >
</behaviorExtensions>
</extensions>
</system.serviceModel>
</configuration>
I was getting the same error. You need to add this entire line to the config file:
<add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
This is from the example. However, I actually used Version=3.5.0.0
I thin you need to add the appropriate config section:
<configSections>
<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</configSections>
You can also handle this via code in one of your startup routines.
Microsoft.IdentityModel.Tokens.FederatedServiceCredentials.ConfigureServiceHost(wcfHost, FederatedAuthentication.ServiceConfiguration);
FederatedAuthentication.ServiceConfiguration.AudienceRestriction.AllowedAudienceUris.Add(endpoint.Address.Uri);