Passing Date parametere from Javascript to WCF

Having a service method that accepts two parameters will look like this:

[DataContract()]
public class ServiceRequest
{
[DataMember()]
Nullable<DateTime> DateTimeFrom {
get; set; }
[DataMember()]
Nullable<DateTime> DateTimeTo {
get; set; }
}

[ServiceContract()]
public interface IService
{
[WebInvoke(UriTemplate =
"getServiceCall", Method = "POST")]
ServResponse GetBusinessObjects(ServiceRequest filter);
}

Now, To start calling this method we need to construct a Json data representing the parameters.

      var fromDate = new Date(2013, 06, 18);
var toDate = new Date();

var datavar = {
DateTimeFrom: fromDate.toMSJSON(),
DateTimeTo: toDate.toMSJSON()
};
var parameters = JSON.stringify(datavar);

But, before calling the toMSJSON on date object we need to define it as follows:

// Let Date type be compatible for Microsoft WCF
Date.prototype.toMSJSON = function () {
/// <summary>Let Date type be compatible for Microsoft WCF.
</summary>

var date = ‘/Date(‘ + this.getTime()  + ‘-0000)/’;

};




Getting DateTime from WCF


// convert WCF date to Javascript
String.prototype.DateWCF = function () {
/// <summary>convert string into Date</summary>
var matches = this.match(//Date(([0-9]+)(?:.*))//);
if (matches)
return new Date(parseInt(matches[1]));
};

Notice that when you use a date in javascript it is representing your local date based on the settings on your systemn and browser. As a result you might pass different notation to WCF. For example, my broweser has an timezone offset of -120 minutes. So when I ask to convert 06/20/2013 02:10:04 I see 2013-06-20T00:10:04.000Z which is perfectly normal because that represents the same exact time as I meant on my browser. Thus WCF will get the correct date aswell.

WCF Authenticate by APIKey

Following my previous note, I want each service have its own authentication mechanics, maybe some public services and some sharing the same authentication manager.

To do so, I will set up different behaviors in my web.config in the servicebehaviors section, and make sure each service points to the corresponding behavior:

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name=
"ProductionServiceBehavior">
<serviceAuthorization serviceAuthorizationManagerType=
"WCFWebHttp.APIKeyAuthorization, WCFWebHttp" />
</behavior>
<behavior name=
"PublicServiceBehavior">
<serviceMetadata httpGetEnabled=
"true"/>
<serviceDebug includeExceptionDetailInFaults=
"false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name=
"WCFWebHttp.ProductionService" behaviorConfiguration="ProductionServiceBehavior">
</service>
</services>

Now, all I need to do is to implement my APIKeyAuthorization class. This class inherits from ServiceAuthorizationManager and overrides CheckAccessCore to validate the request and send an Error response if not validated.
For detailed information about this class see the original article on:
MSDN.

Routing WCF services by code

When you want to route the requests to specific WCF service deppending on the url, you can add routers on the Application_Start method of the Global.asax.cs. In the following example I want my ProductionService handle the service calls on the path starting with /Production/ and my PublicService handle the requests with a path starting with /public/demo/

using System;
using System.Web.Routing;
using System.ServiceModel.Activation;

public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
#region Register Routes
var factory =
new WebServiceHostFactory();
RouteTable.Routes.Add(
new ServiceRoute("Production", factory, typeof(ProductionService)));
RouteTable.Routes.Add(
new ServiceRoute("Public/demo/", factory, typeof(PublicService)));
#endregion
}

Windows Communication Foundation Built-In Bindings

Windows Communication Foundation Built-In Bindings

Binding Class Name Transport Message Encoding Message Version Security Mode Reliable Messaging Transaction Flow (disabled by default)
BasicHttpBinding HTTP Text SOAP 1.1 None Not Supported Not Supported
WSHttpBinding HTTP Text SOAP 1.2 WS-Addressing 1.0 Message Disabled WS-AtomicTransactions
WSDualHttpBinding HTTP Text SOAP 1.2 WS-Addressing 1.0 Message Enabled WS-AtomicTransactions
WSFederationHttpBinding HTTP Text SOAP 1.2 WS-Addressing 1.0 Message Disabled WS-AtomicTransactions
NetTcpBinding TCP Binary SOAP 1.2 Transport Disabled OleTransactions
NetPeerTcpBinding P2P Binary SOAP 1.2 Transport Not Supported Not Supported
NetNamedPipesBinding Named Pipes Binary SOAP 1.2 Transport Not Supported OleTransactions
NetMsmqBinding MSMQ Binary SOAP 1.2 Message Not Supported Not Supported
MsmqIntegrationBinding MSMQ Not Supported (uses a pre-WCF serialization format) Not Supported Transport Not Supported Not Supported
CustomBinding You Decide You Decide You Decide You Decide You Decide You Decide

Linq-To-SQL and WCF

WCF works on the objects like disconnected records. The object that is passed to the client is not the same as the one the is about to update. Therefore Linq does not know about the changes made to the record. As a result Linq will not do anything when calling the SubmitChanges.

To sort out this problem we need attach the instance record again to the list in the context:

context.GetTable().Attach(instance, true);

just before we call the SubmitChanges. But this is not always possible. I got the following error when calling this:

An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.

The simple way of sorting this out was giving the ID field of the record the attribute of

IsVersion=true

This way Linq allows me to attach the existing instance and generate an UPDATE sql-statement.

See Also: http://www.west-wind.com/Weblog/posts/135659.aspx

using UriTemplate

Copied from MSDN:

The UriTemplateTable class provides a mechanism for managing a collection of UriTemplate objects. This makes it easy to call Match on the table to find all templates that match the supplied Uri. Alternatively, you can call MatchSingle to ensure it matches only a single UriTemplate in the table.

Uri baseUri = new Uri("http://contoso.com/bookmarkservice");
UriTemplate uriTemplate = new UriTemplate( "users/{username}/bookmarks/{id}");

// generate a new bookmark URI
Uri newBookmarkUri = uriTemplate.BindByPosition(baseUri, "skonnard", "123");

// match an existing bookmark URI
UriTemplateMatch match = uriTemplate.Match(baseUri, newBookmarkUri);
System.Diagnostics.Debug.Assert(match != null);
Console.WriteLine(match.BoundVariables["username"]);
Console.WriteLine(match.BoundVariables["id"]);