in

mscommunity.net

Interactive mscommunity.net online activities

DamirDobric

prosinac 2008 - Posts

  • Forward-Compatible Data Contracts

    Windows Communication Foundation (WCF) data contract system is that contracts can evolve over time in nonbreaking ways. That is, a client with an older version of a data contract can communicate with a service with a newer version of the same data contract, or a client with a newer version of a data contract can communicate with an older version of the same data contract.

    You can apply most of the versioning features on an as-needed basis when new versions of an existing data contract are created. However, one versioning feature, round-tripping, must be built into the type from the first version in order to work properly.

    Round-Tripping

    Round-tripping occurs when data passes from a new version to an old version and back to the new version of a data contract. Round-tripping guarantees that no data is lost. Enabling round-tripping makes the type forward-compatible with any future changes supported by the data contract versioning model.

    To enable round-tripping for a particular type, the type must implement the IExtensibleDataObject interface. The interface contains one property, ExtensionData (returning the ExtensionDataObject type). The property stores any data from future versions of the data contract that is unknown to the current version.

    Example

    The following data contract is not forward-compatible with future changes.

    [DataContract] public class Contact
    {
       [DataMember]
       public string Name;
    }

    To make the type compatible with future changes (such as adding a new data member named "DisplayNumber"), implement the IExtensibleDataObject interface.

    [DataContract]
    public class Person : IExtensibleDataObject
    {
        [DataMember]
        public string Name;

        private ExtensionDataObject theData;
        public virtual ExtensionDataObject ExtensionData
        {
            get { return theData; }
            set { theData = value; }
        }
    }

    For more information, see Best Practices: Data Contract Versioning.

  • Performance Comparison: SOAP vs. JSON (WCF-Implementation)

    As you probably know the JSON is more compact format than SOAP, which is very usable when you want to reduce the traffic on the network. To illustrate this, assume there is a class called Airport which looks like shown below:

    image

    When this class is serialized by using of DataContractSerializer the result is:

    <a:Airport><a:Contacts><a:Contact><a:FirstName>huso</a:FirstName><a:LastName>djimbilic</a:LastName></a:Contact>
    <a:Contact><a:FirstName>haso</a:FirstName><a:LastName>zgembic</a:LastName></a:Contact></a:Contacts ></a:Contact></a:Contacts><a:Latitude>-161.837997</a:Latitude><a:Longitude>60.779778</a:Longitude><a:Name>PABE</a:Name></a:Airport>

    When using REST based service with JSON serialization (DataContractJsonSerializer) the instance of the airport-class sent over the network would look like:
    {"Contacts":[{"FirstName":"huso","LastName":"djimbilic"},{"FirstName":"haso","LastName":"zgembic"}],"Latitude":87.652778,"Longitude":34.691111,"Name":"5AL5"}.

    My intension is not to describe in detail differences between this two formats, but it is obvious, that the JSON is much compacter.

    When we now this, it reasonable to expect that the time needed for consuming of SOAP messages in comparison to JSON messages correlate to the amount of data. If you think this, you are wrong :)

    Clearly it means: SOAP transmits 20-40% more data than JSON, but it is (in WCF) faster approximately 20-25% than JSON. How this is possible?  The reason is in WCF-JSON implementation itself. WCF internally serializes JSON streams to some kind of XML-Infoset wire format that requires about 50% more bytes than DataContractSerializer.

    Comparison by time

    Following diagram shows comparison between JSON and SOAP messaging in ten successively repeated tests. Values
    in diagram are given in seconds for 3000 repeats per test. For example the first sample for JSON has taken 14 seconds and 10 seconds for SOAP each 3000 repeats. One repeat means send one request and receive response.
    In this specific test we retrieved 101 instances of the class Airport (see below XML description of this type).

    image

    Exact values in seconds measured in this test ar given in the next table:

    JSON SOAP
    14 10
    17 11
    15 12
    16 13
    17 14
    18 14
    19 15
    20 16
    20 17
    22 18

     

    Comparison by network traffic

    JSON (15862 bytes)

    Request

    GET /GetJsonCoordinates.svc/GetCoordinates HTTP/1.1

    Content-Type: application/xml; charset=utf-8

    VsDebuggerCausalityData: uIDPo3f2jA1vh9tDhVf/HkaioegAAAAAjmFHoP+8OkyjmjyXSmDL4rwAh+pBIIdPmQ0493uxJYcACQAA

    Host: dado-nb0:81

    Connection: Keep-Alive

    Response

    HTTP/1.1 200 OK

    Content-Type: application/json; charset=utf-8

    Server: Microsoft-IIS/7.0

    X-Powered-By: ASP.NET

    Date: Fri, 26 Dec 2008 23:13:23 GMT

    Content-Length: 15852

     

    [{"Contacts":[{"FirstName":"huso","LastName":"djimbilic"},{"FirstName":"haso","LastName":"zgembic"}],"Latitude":87.652778,"Longitude":34.691111,"Name":"5AL5"},{"Contacts":[{"FirstName":"damir","LastName":"dobric"},{"FirstName":"alvin","LastName":"dobric"}],"Latitude":-85.468,"Longitude":32.220147,"Name":"AL05"},{"Contacts":[{"FirstName":"damir","LastName":"dobric"},{"FirstName":"alvin","LastName":"dobric"}],"Latitude":-86.124964,"Longitude":32.358472,"Name":"AL12"}:"dobric"},{"FirstName":"alvin","LastName":"dobric"}],"Latitude":-161.837997,"Longitude":60.779778,"Name":"PABE"}]

     Note: Response not complete!

    SOAP (31872 bytes)

    Request

    POST /GetSoapCoordinates.svc HTTP/1.1

    Content-Type: text/xml; charset=utf-8

    VsDebuggerCausalityData: uIDPo3j2jA1vh9tDhVf/HkaioegAAAAAjmFHoP+8OkyjmjyXSmDL4rwAh+pBIIdPmQ0493uxJYcACQAA

    SOAPAction: "http://tempuri.org/ISoapGpsService/GetCoordinates"

    Host: dado-nb0:81

    Content-Length: 203

    Expect: 100-continue

    Connection: Keep-Alive

     

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetCoordinates xmlns="http://tempuri.org/"><area>GER</area><numOfRecords>100</numOfRecords></GetCoordinates></s:Body></s:Envelope>

    Response

    HTTP/1.1 200 OK

    Content-Type: text/xml; charset=utf-8

    Server: Microsoft-IIS/7.0

    X-Powered-By: ASP.NET

    Date: Fri, 26 Dec 2008 23:15:44 GMT

    Content-Length: 31872

     

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetCoordinatesResponse xmlns="http://tempuri.org/"><GetCoordinatesResult xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.ServiceModel.Samples.BasicSyndication" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <a:Airport><a:Contacts><a:Contact><a:FirstName>huso</a:FirstName><a:LastName>djimbilic</a:LastName></a:Contact><a:Contact><a:FirstName>haso</a:FirstName><a:LastName>zgembic</a:LastName></a:Contact></a:Contacts ></a:Contact></a:Contacts><a:Latitude>-161.837997</a:Latitude><a:Longitude>60.779778</a:Longitude><a:Name>PABE</a:Name></a:Airport></GetCoordinatesResult></GetCoordinatesResponse></s:Body></s:Envelope>

    Note: Response not complete!

    Posted pro 27 2008, 03:49 by anonymous
    Filed under:
  • ServiceHost Error

    Problem Description

    Operation "xxx" of contract 'yyyy' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped.

     

    Solution

    This error occurs while starting of the web service host:

    1)  explicitly in the custom host:
        WebServiceHost xmlHost = new WebServiceHost(. . .) or

    2)  implicitly by using of SVC-file in IIS host:

         <%@ ServiceHost Language="C#" Debug="true" Service=". . ."
                    Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

    The problem is caused by using of the usual service contract, which is styled for standard SOAP-Host (ServiceHost) and not as expected for the WebServiceHost.

    This is an example of the contract which cause this error:

    [OperationContract]
    Airport[] GetCoordinates(string area, int numOfRecords);

    To fix it, use REST-specific styling of the operation as shown below, or use ServiceHost instead of WebServiceHost.

    [OperationContract]
    [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]
    Airport[] GetCoordinates(string area, int numOfRecords);

    or

    <%@ ServiceHost Language="C#" Debug="true" Service=". . ." %>

  • Consuming REST Services with WCF-Clients

    This post describes how to consume the REST Service with WCF-based client. In general there are two ways to do this:

    1. You send the HTTP request and serialize the data
    2. You let the WCF to do this for you.

    Actually, you might be interested to do this by using of variant 2. However I will show the first the variant 1 to get more ffeling what happens behind the scene.

    In this example I have used the service with following contract:

    [ServiceContract()]
    public interface IJsonGpsService
    {
      [OperationContract]
      [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
             ResponseFormat = WebMessageFormat.Json)]

       Airport[] GetCoordinates();
    }

    The service IJsonGpsService retrieves the GPS coordinates of all airports in the array of Airport. If the service is setup for JSON serialization as shown in the interface above you can test it by simply entering of the URL in the browser's address window:

    http://localhost:81/GetJsonCoordinates.svc/getcoordinates

    After sending of request the browser (in my case IE) will popup following dialog:

    image
    This means that the browser cannot deserialize the JSON data. Anyhow, you can save the response in the file and open it. In this case the response in the file would look like:
     

    {"d":[{"__type":"Airport:#Microsoft.ServiceModel.Samples.BasicSyndication","Contacts":[{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"damir","LastName":"dobric"},{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"alvin","LastName":"dobric"}],"Latitude":-87.652778,"Longitude":34.691111,"Name":"5AL5"},{"__type":"Airport:#Microsoft.ServiceModel.Samples.BasicSyndication","Contacts":[{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"damir","LastName":"dobric"},{"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"alvin","LastName":"dobric"}],"Latitude":-
    ..
    {"__type":"Contact:#Microsoft.ServiceModel.Samples.BasicSyndication","FirstName":"alvin","LastName":"dobric"}],"Latitude":-161.837997,"Longitude":60.779778,"Name":"PABE"}]}

    It is obvious that the browser cannot understand this response. To make the response more understandable for browser the contract could to be slightly changed  to enforce XML serialization (in a case of WCF this means DataContractSerializer by default):

    [ServiceContract()]
    public interface IJsonGpsService
    {
      [OperationContract]
      [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
             ResponseFormat = WebMessageFormat.Xml)]

       Airport[] GetCoordinates();
    }

    Rebuild the service and enter again the same URL in the browser. This is now the XML-based snapshot of the response:

    image

     

    Consuming with serialization

    To consume this service by using of the first variant you are responsible to send the request and to serialize the data. Assuming that the WCF service is build by using of WCF-technology, it is likely that the data on the wire are serialized by using of DataContractSerializer. Another alternative would be using of XmlSerializer. Here is the full example which shows how to do this:

    WebRequest request = WebRequest.Create(
    “http://localhost:81/GetJsonCoordinates.svc/getcoordinates");

    WebResponse ws = request.GetResponse();
    DataContractSerializer ser =
    new DataContractSerializer(typeof(Airport[]));

    //
    // here is another alternative.
    //XmlSerializer ser = new XmlSerializer(typeof(Airport[]));
    Airport[] airports = (Airport[])ser.ReadObject(ws.GetResponseStream());

     

    Consuming with real WCF client

    In the real world you will and should not do it this way. You would probable open VS and add service reference. Unfortunately this will not help you mach. The bindings created on the client side will be invalid and two endpoint will be created. It will not work.
    To make it working do folowing:

    1. Add service reference by using the URI http://localhost:81/GetJsonCoordinates.svc. (assuming that MEX binding is enabled).
    2. Remove one of two created bindings in the client's configuration file (under the section <client>).
    3. Add the endpoint behavior ("AjaxBehavior") with the webHtt element (enableWebScript is required for AJAX).
    4. Add the webHttpConfiguration element (if some none-default settings are used - in this example basic-clear text. Do not use this in productive environment!)

    5. Add the address element in the endpoint with the URI of the service. (VS does not add this by adding of reference)
    6. Finally change the interface which has been automatically created by WS during add service reference operation, as shown below:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IJsonGpsService")]
    public interface IJsonGpsService
    {   
      
    [System.ServiceModel.OperationContractAttribute 
       (Action=http://tempuri.org/IJsonGpsService/GetCoordinates,
        ReplyAction=http://tempuri.org/IJsonGpsService/GetCoordinatesResponse)
       [WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
        ResponseFormat = WebMessageFormat.Xml)]TestClient.ServiceReference1.Airport[]
        GetCoordinates();
    }

    In the interface above I have added the WebGet attribute. VS didn't create this automatically.

    Here is the full configuration which corresponds to changes described in steps 1-5 above:


    image

    Following code snippet shows the consumer's code which consumes the REST-service by using of WCF. Before this code can run you have to perform changes described in the step 6 above.

    JsonGpsServiceClient json = new JsonGpsServiceClient();

    json.ClientCredentials.UserName.UserName = "..";
    json.ClientCredentials.UserName.Password = "..";


    airports = json.GetCoordinates();

     

    Lst but not least: Please note that the message format defined in the interface at both sides has to be the some. If it is not the same (for example Service JSON and Client XML) no exception will be thrown, but the data in the response will be empty as shown in the next picture:
    image

  • Working with IIS7 Authentication and WCF

    When hosting your service in IIS, sometimes you may decide to protect it by using of for example Basic Authentication. In this case I assume that secured transport (ssl) is used, because the username and password are base64 encoded (clear text).

    Unfortunately, in this case you may get following error, which can be confusing:

    Server Error in '/' Application.


    Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.NotSupportedException: Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    This error appears if you have setup your IIS-application to use Basic Authentication only (Anonymous Authentication is disabled).

    image

    Usually the error will appear in this case if you have configured an additional endpoint which requires anonymous authentication, like MexHttpBindig.

    Solution

    1. Enable Anonymous authentication (required by MEX-Binding) or
    2. Remove MEX-Binding from configuration file.

    Posted pro 23 2008, 10:50 by anonymous
    Filed under:
  • VPN issue with PPTP and Windows Vista

    I have been using VPN connection on Windows Vista since very early CTP version of Vista. All worked fine till today. Without of any plausible reason, the VPN has stopped working. I spent probably four hours of my life to fix this. Honestly I spend four hours for ever for some stupid Vista-Networking thing and hope this post will help you to spend few hours longer for some much more interesting peace of life.

    When you start VPM connection you will notice that the connecting window is hanging for minutes and after all it pop-ups you some error message. Please do not read it, it will confuse you more than you can expect. Because of this I will not paste it here. :)

    More interesting message is in event log:

    CoId={3AB760CF-41C9-4267-999F-57AC7E079137}: The user *** dialed a connection named *** which has failed. The error code returned on failure is 800.

    This message is not confusing, but the entropy of useful information could sometimes be high. Unfortunately in my specific problem, this message has not useful information at all (too).

    If you have installed Virtual PC 2007 on your machine, it can happen that some windows update (I would really like to know which one) destroy some kind of mapping between VPN connection and WAN Miniport driver. Usually, the VPN should be bound on WAN Miniport (PPTP) like shown in the picture below:

    image

    After this mapping is damaged, you will notice that instead of PPTP L2TP is mapped.

    To workaround the problem open the dialog with properties of physical network adapter (for example WLAN adapter) and notice "Virtual Machine Network Services".

    image

    Select it and press button "Uninstall". After few seconds try to connect via VPN again. This should work now, without of restarting of the machine.

    hhhmmm, one may think now, this sounds too simple to be true. :) This is true, because after uninstalling of "Virtual Machine Network Services" the virtual machine will no more work. Fortunately, this can be easily fixed too. Start VPC and one dialog will appear, which notifies you that virtual network service are missing on the machine. Press button "Yes" and VPC will install it again automatically.

     

    Last, but not least. If you are happy user of T-Mobile UMTS express card, the card will in this case not work too. The error message, which describes the problem would have less entropy than zero if would be mathematically possible. If you really want to read some much more crazy thing please go here.

     

    [Visit: www.daenet.de]

  • Hot Topic: Wie unterscheiden/ergänzen sich BizTalk Server und Dublin?

    Der BizTalk Server agiert als Integrationsserver und wird häufig auch als Connectivity Server bezeichnet, wohingegen Dublin“ der auf Windows basierende Application Server ist und als Host für WF und WCF Dienste fungiert.

    Vereinfacht kann man sagen, dass der BizTalk Server als Integrationsserver den Application Server Dublin ergänzt, wenn

    · Zahlreiche Systeme zu integrieren sind – one-to-many oder many-to-many,

    · Businss-to-Business Prozesse implementiert werden sollen und danach zu überwachen sind,

    · Spezielle Schnittstellen und Standards benötigt werden, die bereits im BizTalk Servers enthalten sind,

    · Business Activity Monitoring (BAM) gefordert ist,

    · EDI oder RFID Funktionen benötigt werden. Hierzu kann man technisch auf BTS verzichten, wenn man BTS Lizenz hat, da RFID Server unabhängig vom BTS Host ist.

    · Skalierbarkeit benötigt wird.

    Posted pro 05 2008, 12:34 by anonymous
    Filed under:
Powered by Community Server (Commercial Edition), by Telligent Systems