Showing posts with label wcf. Show all posts
Showing posts with label wcf. Show all posts

Sunday, October 30, 2011

Creating a secure RESTfull wcf service and consume it cross domain with jquery using basic authentication

Last week I was very busy trying to create a secure wcf service which can be consumed using jquery jquery and wcf. There are a lot of resources (see References below) but none of them contain the full working package. Below I try to highlight the steps of creating the service and consumer. And because a sample says more than a thousand words, you can download it here.

Note:
The solution only works when the wcf service is hosted using iis. I have not tried to create the service using the self-hosting feature of wcf.


Note 2:
For basic authentication to be secure, you need to access it using SSL.


Step 1. Create your basic interface using the WebGet and WebInvoke
[OperationContract]
[WebGet(UriTemplate = "get/Do/{echo}", ResponseFormat = WebMessageFormat.Json)]
DoResponse Do(string echo);

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "post/Do/{echo}", ResponseFormat = WebMessageFormat.Json)]
DoResponse DoPost(string echo);


Step 2. Enable cross domain calls using the global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
    EnableCrossDomainAjaxCall();
}

private void EnableCrossDomainAjaxCall()
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");

    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept");
        HttpContext.Current.Response.End();
    }
}


Step 3. Configure the basic html module
<bindings>
    <webHttpBinding>
        <binding name="BasicAuthentication">
            <security mode="TransportCredentialOnly">
                <transport clientCredentialType="Basic" />
            </security>
        </binding>
    </webHttpBinding>
</bindings>

<serviceBehaviors>
<behavior>
    <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
    <serviceMetadata httpGetEnabled="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="false"/>
    <serviceAuthorization serviceAuthorizationManagerType="WcfSampleApp.Wcfservice.BasicAuthorization, WcfSampleApp.Wcfservice" />
</behavior>
</serviceBehaviors>


Step 4. Call the service using jquery ajax using basic authentication header.
$.ajax( {
 url : 'http://localhost:35461/SampleApp.svc/get/Do/same problem',
 dataType: 'json',
 type: "GET",
 beforeSend : function(xhr) {
     xhr.setRequestHeader("Authorization", "Basic " + encodeBase64("sameproblem:morecode"));
 },
 error : function(xhr, ajaxOptions, thrownError) {
     $('#GetDiv').html("error");
 },
 success : function(model) {
     $("#GetDiv").html(model.Echo);
 }
});


Download example solution

References:
http://msdn.microsoft.com/en-us/library/dd203052.aspx
http://stackoverflow.com/questions/1640391/how-do-i-make-a-jsonp-call-with-jquery-with-basic-authentication
http://blog.rassemblr.com/2011/05/jquery-ajax-and-rest-http-basic-authentication-done-deal/
http://www.codeproject.com/KB/ajax/jQueryWCFRest.aspx
http://msdn.microsoft.com/en-us/magazine/cc948343.aspx
http://weblogs.asp.net/cibrax/archive/2009/03/20/custom-basic-authentication-for-restful-services.aspx

Tuesday, September 6, 2011

WCF using svc files in IIS and the maximum message size quota exceeded error

When using WCF you can (and will ;) ) run into the following exception when posting messages:
The maximum message size quota for incoming messages (65536) has been exceeded.
Normally you can easily edit the config files and bind the right endpoint to the right bindingconfiguration and it workt. But how can you do that when using wcf by calling svc files hosted on an IIS server which have no endpoint configured. I've been struggling with this for hours and I can finally give you the answer! You'll have to match the service name with the full classname (including) namespace. After that you can setup the max length and for example ssl (https support). MailService.svc.cs:
namespace SC.MessageGateway.WcfService
{
    public class MailService : IMailService
    {
        // ...
    }
}
Web.Config:
<system.serviceModel>
    <services>
        <service name="SC.MessageGateway.WcfService.MailService">
            <endpoint address=""
                      binding="basicHttpBinding"
                      bindingConfiguration="LargeMessageSizeAndHttps"
                      contract="SC.MessageGateway.Communication.ServiceContracts.IMailService" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    <bindings>
        <basicHttpBinding>
            <binding name="LargeMessageSizeAndHttps" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
                <!-- Enable Https -->
                <security mode="Transport">
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
</system.serviceModel>
This answer was found with the help of Ladislav Mrnka's response in:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/a7ebf86b-7d47-43c8-84d0-f8be17d42ab9/

Thursday, February 10, 2011

A call to SSPI failed, see inner exception.

When using netTcpBindings on WCF endpoints, make sure to add
<identity><dns value="{nameofserver}"></identity>
between the begin and end tag of the endpoint, or make use of an IP instead of a DNS name.