Quantcast
Channel: Distributed Services: Notes from the field
Viewing all 164 articles
Browse latest View live

Using X509IncludeOption to avoid "System.Security.Cryptography.CryptographicException: A certificate chain could not be built to a trusted root authority"

$
0
0

In the System.Security.Cryptography.X509Certificates namespace, X509IncludeOption is an enumeration that is defined as:

public enum X509IncludeOption
{
    None,
    ExcludeRoot,
    EndCertOnly,
    WholeChain
}

http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509includeoption(v=vs.110).aspx has all the details regarding the above enumeration, but for clarity here is a brief summary.

The enum specifies the amount of the certificate chain that should be included in the X.509 data.

None             - No chain information should be included.
ExcludeRoot - Except the root certificate the full chain is included.
EndCertOnly - This means the leaf certificate should be included in the X.509 data.
WholeChain  - The entire chain from the root to the leaf.

At times while trying to compute a signature or verifying a certificate chain we get an exception saying: System.Security.Cryptography.CryptographicException: A certificate chain could not be built to a trusted root authority.

Ideally a CAPI2 trace can provide more information on why the certificate chain verification failed. If you are using the SignedCms class for computing signature then also the chain will be verified and can fail if the chain building fails.

A quick way to test the chain is to use X509Chain.Build method which builds an X.509 chain using the policy specified in X509ChainPolicy.

Example:

X509Chain ch = new X509Chain();
ch.Build (certificate);

If the chain building fails and you would still like to use the existing certificate to get past the crypto exception then you can use the X509IncludeOption enumeration to exclude the chain, for example you can try using X509IncludeOption.EndCertOnly and see if that helps in getting past the crypto exception.

For example the code below shows the usage of SignedCms to compute a signature and use it to encode the information in the object into a PKCS#7 message.

ContentInfo contentInfo = new ContentInfo(hashData);       // ContentInfo represents the CMS/PKCS #7 ContentInfo data structure.
// Create an instance of the SignedCms class by using the specified content information as the inner content.
SignedCms signedCms = new SignedCms(contentInfo);    // SignedCms class enables signing and verifying of CMS/PKCS #7 messages.
CmsSigner cmsSigner = new CmsSigner(cert);                  // CmsSigner class provides signing functionality.

signedCms.ComputeSignature(cmsSigner, false);             // ComputeSignature(CmsSigner) method creates a signature using the specified signer and adds the signature to the CMS/PKCS #7 message. The 2nd parameter which is false prompts the user to select a signing certificate.
byte[] encoded_msg = signedCms.Encode();                     // The Encode method encodes the information in the object named signedCms into a CMS/PKCS #7 message.

If the above code fails because of "System.Security.Cryptography.CryptographicException: A certificate chain could not be built to a trusted root authority" you can try adding the line below immediately before computing the signature and see if it avoids the problem. Ofcourse you can tweak using the other enum options for a check. However this is a temporary workaround and the actual issue of why the chain building failed should be investigated further.

cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;


COM+ application recycling

$
0
0

Clarifying answers to some questions.

-is there any know issues with application recycling, especially on memory limit?

 

General Information

================

Application recycling works by creating a duplicate of the Dllhost process associated with an application. This duplicate Dllhost process services all future object requests, which leaves the old Dllhost to finish servicing the remaining object requests. The old Dllhost process is shut down when it detects the release of all external references to objects in the process or when the expiration time-out value is reached. Through this behavior, application recycling ensures that a client application does not experience a service interruption.

 

On memory limit

=============

RecycleMemoryLimit - The maximum amount of process memory usage (in kilobytes) before recycling the process. If the process memory usage exceeds the specified number for longer than one minute, the process is recycled. The valid range is 0 through 1,048,576 KB. The default amount of memory usage is 0 KB, which indicates that the process will not recycle from reaching a memory limit.

 

Known Issues

==========

1. You cannot recycle a COM+ application that has been configured to run as a Windows service.

 

2. Memory Limit indicates the maximum amount of process memory usage (in kilobytes) before recycling the process. If the process's memory usage exceeds the specified number for longer than one minute, the process is recycled. The valid range is 0 through 1,048,576 KB, and the default amount of memory usage is 0 KB.

 

-is it recommended or not to use this feature?

 

Application recycling significantly increases the overall stability of your applications. Because the performance of most applications can degrade over time due to factors such as memory leaks, reliance on third-party code, and non-scalable resource usage, COM+ application recycling provides a simple solution to gracefully shut down a process associated with an application and restart it. So it is a recommended feature.

 

-the memory limit, is it based on the COM+ process private bytes or other?

 process memory usage (in kilobytes)

 

More Info and reference:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms685957(v=vs.85).aspx

CreateRequest method from IX509Enrollment

$
0
0

The CreateRequest method retrieves an encoded PKCS#10 certificate request.
This method uses the information provided during initialization and other properties that have been specified, creates a dummy certificate and places it in the request store.

Here is the flow: CreateRequest() forces creation of a dummy certificate and calls a method to get the private key. It checks to see if the private key exists or not. If you don't set the signing certificate then it will create a dummy certificate and won't ask for the private key. If you do set the signing certificate then you have to use one from the certificate store that has a private key.

Example:

CX509PublicKey publicKey = new CX509PublicKey();
publicKey.Initialize(oidx, key, EncodedValue, EncodingType.XCN_CRYPT_STRING_HEX);

string templateName = "User";

IX509CertificateRequestPkcs10 certificateRequestPkcs10 = new CX509CertificateRequestPkcs10();

certificateRequestPkcs10.InitializeFromPublicKey(X509CertificateEnrollmentContext.ContextUser,
publicKey, templateName);

certificateRequestPkcs10.Encode();

IX509Enrollment2 objEnroll = new CX509Enrollment();

CX509CertificateRequestCmc cmcRequest = new CX509CertificateRequestCmcClass();

cmcRequest.InitializeFromInnerRequest(certificateRequestPkcs10);

objEnroll.InitializeFromRequest(cmcRequest);

objEnroll.CreateRequest();

 

Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/aa377869(v=vs.85).aspx

COM client failing with error 8000401a

$
0
0

The error 8000401a (CO_E_RUNAS_LOGON_FAILURE) means "The server process could not be started because the configured identity is incorrect. Check the username and password".

Many a times we have seen that the error occurs from a DCOM server that is configured to launch as “The Interactive User” user account especially on Windows Vista and above OS's. This worked fine on Windows 2003 but on Windows Vista and above OS's you notice certain scenarios where the application fails to launch. For example,

a. If you log off the machine and don’t have a remote desktop session connected to the server OR

b. You disconnected a RDP session (that was used to connect to the DCOM server machine) without logging off.

This is by design due to new session management features of Windows Vista and above OS's.

Both (a) & (b) are similar with respect to interactive user logon. Reason: Disconnecting a RDP session means "no currently interactive user logged on". This makes sense because an "interactive logon" would mean that someone actually has the ability to respond to some GUI based features should the DCOM server use any GUI items. If you’ve closed down a RDP session and/or don’t have anyone logged onto the machine then if the DCOM server does require GUI response, it will hang because there is no interactive session to respond to it.

The best possible ways to resolve this is by:

(I) Change the identity of the DCOM server from “The Interactive User” to “This User” and then specify that the DCOM server runs as admin or some other domain or local user account.

(II) Make sure that someone is physically logged onto the machine or that you continuously have a remote desktop session open.

Applies to:

 

Additional References:

http://msdn.microsoft.com/en-us/library/cc226962.aspx

http://msdn.microsoft.com/en-us/library/aa383835(v=vs.85).aspx

 

SSL offloading in load balancer scenario

$
0
0

Problem description

WCF service hosted on IIS runs over http behind load balanced servers. The load balancer is configured to perform ssl offloading.

The WCF service is perfectly browsed on the server box over http. The same service is also browsed properly without any issues at the client side. When we consume the wsdl and hit the service request using any tool, there was no response from the service.

                                        Client(https)    --->>>>    LoadBalancer     ---->>>>      Service(http)

Issue

The only issue is with metadata. When we take a peek at the address in the SOAP:Address, it still used to point to http address for the https wsdl.

Service URL: https://www.myserver.com/Service/TestService.svc?wsdl

And, its wsdl looks like the following:

      <wsdl:service name="TestService">

  <wsdl:port name="BasicHttpBinding_ITestService" binding="tns:BasicHttpBinding_ITestService">

<soap:address location="http://www.myserver.com/Service/TestService.svc" />

           </wsdl:port>

      </wsdl:service>

 

This means though the client tries to access the service over https, it still gets redirected to http because of soap:address location. 

 

Approach 1

Use the following cusotmBinding in service web.config:

       <customBinding>

               <binding name="serviceBinding">

                     <textMessageEncoding>

                               <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" />

                     </textMessageEncoding>

                     <security allowInsecureTransport="true" enableUnsecuredResponse="true">

                           <secureConversationBootstrap requireDerivedKeys="false" />

                    </security>

                    <httpTransport maxReceivedMessageSize ="2147483647" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" />

               </binding>

       </customBinding> 

 

If enableUnsecuredResponse value set to true, the following new features are enabled in WCF:

  1. WCF clients can accept unsecured responses even if the outgoing messages are secured by using the Secure Socket Layer (SSL) protocol to sign the message body.
  2. WCF services can send unsecured responses that have no security header in SOAP envelopes even if the request is secured.

      Reference: http://support.microsoft.com/kb/971493

If allowInsecureTransport value set to true, Mixed-Mode security binding with http as the transport is allowed instead of the secure https option.

If requireDerivedKeys value set to false, it will specify the keys won’t be derived from the original proof keys.

Other values are just set to the highest values, because we had to accommodate large data transfer too.

In order to test on the client,

  1. Take a console application
  2. Add service reference
  3. Modify app.config binding to use the same customBinding as of service web.config
  4. The test will be successful

 

Approach 2

Another alternative is to modify the wsdl completely, and make it available over https on the service side.

This involves modifying the wsdl location to point to a virtual directory and state explicitly that metadataLocation is modified to the virtual directory instead of the actual schema.

 

How can we make it?

Create a folder named Metadata.

Download metadata by visual studio command prompt:

>svcutil /t:metadata https://www.myserver.com/Service/TestService.svc?wsdl

It will download a list of xsd and wsdl files.

 

Let us target wsdl files first and then the xsd files in order to modify namespace and schmeLocation to point out to https.

singleWsdl

Wsdl

  • Identify custom namespaces, modify namespace links to https. Ensure xmls:tns and targetNamespace values are same (we need not modify this)
  • Modify wsdl:import to the https namespace and schema location over https to the virtual directory
  • Modify soapAction to https
  • Modify soapAddress location in <wsdl:service> to https URI pointing to the service file

Individual xsd files

  • Modify xmlns:tns and targetNamespace values to https://www.myserver.com/Service/XsdFile1
  • Basically xsd schema location would have been like ?xsd=xsd0/1… We will hard code this to certain file
  • And the same approach can be followed for other xsd files

 

Once all the individual changes are made. These wsdl/ xsd files can be published to the IIS virtual directory. So, next time whenever the metadata request will be made – it will point to the hard coded paths in the wsdl and xsd files.

If you are publishing via visual studio, please ensure to change the Build Action for those files to Content type.

 

How can service make local metadata available?

Modify service behavior in the web.config as the following:

      <serviceBehaviors>

            <behavior name="CustomBehavior">

                   <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" externalMetadataLocation="https:// www.myserver.com/ Service /TestService.wsdl" />

            </behavior>

      </serviceBehaviors>

 

Use basciHttpBinding for simplicity sake:

       <basicHttpBinding>

              <binding name="BasicHttpBinding_ITestService">

                    <security mode="None" />

              </binding>

       </basicHttpBinding>

 

Important

  • The time can only be saved if proper namespace pattern is followed while designing the contracts for your WCF service.
  • The process is purely manual. Pay keen attention and modify schemaLocation and namespace to https based url (all will associate to the newly create metadata files and be available in IIS virtual directory explicitly).
  • Though the service will be accessible on https, it still runs on http inside server box.
  • Approach 2 is recommended in comparison in case of non-.net client (tested in case of Java client).

 

Created by
Purna Chandra Panda (MSFT)

WCF: Consuming WCF Web Service in a DLL

$
0
0

 

Problem Statement:

We have requirement where we need to consume a service (asmx or WCF) in a class then we need to consume that class in client application to get the response from service. But the problem arises as configuration of the class (which is consuming the service) in app.config will be loaded into an app.config and this configuration file will not be read if the dll is referred in the application.

 

This will throw the following error:

"Could not find default endpoint element that references contract 'MyService.IService1' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element"

Demo:

1-      WCF service http://localhost:54655/Service1.svc

2-      DLLClass: A class library project which is consuming the WSDL, I call this project as DLLClass. Here is the implementation.

                I.    Create a Class Library project DLLClass.
                II.   Add Service Reference of the service http://localhost:54655/Service1.svc , I named it as Myservice
                III.  Write a method in DLLClass as below:

 

 

 WCFResponse method gets the response from WCF service, http://localhost:54655/Service1.svc.

 

Build this class and we will be using this class in console application by referencing it as dll.

 

3- Create a new Console application ProxyDLLConsole and add the reference of DLLClass dll. Now we will use the WCFResponse method of Class1 in DLLClass dll to connect with the WCF service. Following implementation is the sample:

 

 

Now, press F5 to run the ProxyDLLConsole. And we get the following error.

 

 

 

 

So as per the error message, either the configuration details of the service is not available or there is no endpoint available where the service runs. But my service is up and running. So let’s concentrate on the configuration part of the error message. Let’s have a look into the app.config of ProxyDLLConsole. Below is the app.config:

 

 

Here is the problem, no details of service end point so the above error makes sense as the calling process is not able to identify the configuration details of the service. This implementation will always fail.

 

Now what can be done to overcome this?

 

Solution:

 

Let’s have look into the app.config of DLLClass class library project.

 

 

This configuration detail is contains the service endpoint information. But it is not getting loaded when the ProxyDLLConsole loads this dll. So to get it working, copy the configuration from the app.config of DLLClass to that of ProxyDLLConsole. So your app.config of ProxyDLLConsole will look like as below:

 

 

 

Now let’s test it and it worked and I am getting the response.

This is happening because app.config of the executing process will always be looked up for the configuration. If the configuration is not available there the configuration should go with dll itself as build.

 

 

 

Note:Configuration details can be embedded into the class library itself if the service metadata are loaded at run time. This way we need not to merge the app.configs explained above.

 Ashutosh Tripathi,

Microsoft India

 (MSFT)

 

 

 

 

 

 

 

 

WCF: Concept of FLAT WSDL

$
0
0

 

Ask:

Java Client (Non.Net client) unable to consume the WCF service WSDL document.

 

Reason:

After collecting fiddler traces from client side, I see that there is a problem while trying to get the XSD downloaded.

WCF expose XSD via external location and sometime Java client may not be able to access them.

 

Fiddler Traces extract:

First request from svcutil.exe

GET https://XYZ.com.com/MyService/MyServiceFile.svc?wsdl
HTTP/1.1

Response, we do get the WSDL doc:

========

HTTP/1.1 200 OK

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

<?xml version="1.0" encoding="utf-8"?>

<wsdl:definitions
name="MyServiceFile" targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
xmlns:wsa10="http://www.w3.org/2005/08/addressing"
xmlns:tns="http://tempuri.org/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy"
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">

 <wsp:Policy
wsu:Id="MyRoutingEndpoint_policy"><wsp:ExactlyOne><wsp:All><sp:TransportBinding
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"><wsp:Policy><sp:TransportToken><wsp:Policy><sp:HttpsToken
RequireClientCertificate="false"/></wsp:Policy></sp:TransportToken><sp:AlgorithmSuite><wsp:Policy><sp:Basic256/></wsp:Policy></sp:AlgorithmSuite><sp:Layout><wsp:Policy><sp:Strict/></wsp:Policy></sp:Layout></wsp:Policy></sp:TransportBinding></wsp:All></wsp:ExactlyOne>

</wsp:Policy>

 <wsdl:types>

<xsd:schema
targetNamespace="http://tempuri.org/Imports">

<xsd:import
schemaLocation="http://XYZ.com.com/MyService/MyServiceFile.svc?xsd=xsd0"
namespace="http://tempuri.org/"/>

<xsd:import
schemaLocation="http://XYZ.com.com/MyService/MyServiceFile.svc?xsd=xsd1"
namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>

<xsd:import
schemaLocation="http://XYZ.com.com/MyService/MyServiceFile.svc?xsd=xsd2"
namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>

<xsd:import
schemaLocation="http://XYZ.com.com/MyService/MyServiceFile.svc?xsd=xsd3"
namespace="http://schemas.datacontract.org/2004/07/McAfeePortal.MyService"/>

<xsd:import
schemaLocation="http://XYZ.com.com/MyService/MyServiceFile.svc?xsd=xsd4"
namespace="http://schemas.datacontract.org/2004/07/McAfeePortal.PurchaseMailService"/>

</xsd:schema></wsdl:types><wsdl:message

 

Second: Because of wrong Schema location, we end up in sending the request to wrong address:

GET http://XYZ.com.com/MyService/MyServiceFile.svc?xsd=xsd0
HTTP/1.1

Because of this issue, my reference.cs file is blank.

 

Options:

Considering the requirement, the feature is added in latest and greatest WCF 4.5.

But what about client running on 4.0 ?

 

Solution:

Using WCF extensibility we can achieve this by implementing the - IWsdlExportExtension

public class MyFlatWsdl : IWsdlExportExtension,IEndpointBehavior  

{      

public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)

       {

           //throw new NotImplementedException();

       }

public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)       

      {

           XmlSchemaSet schemaSet =exporter.GeneratedXmlSchemas;

           foreach (System.Web.Services.Description.ServiceDescription wsdl in exporter.GeneratedWsdlDocuments)

           { 

                List<XmlSchema> importsList = new List<XmlSchema>();

                foreach(XmlSchema schema inwsdl.Types.Schemas)

                       AddImportedSchemas(schema,schemaSet, importsList);

                 if(importsList.Count == 0)

                       return; 

                wsdl.Types.Schemas.Clear();

                foreach(XmlSchema schema in importsList)

                {

                    RemoveXsdImports(schema);                   

                    wsdl.Types.Schemas.Add(schema);

                }

           }

       }

 

private voidAddImportedSchemas(XmlSchema schema, XmlSchemaSet schemaSet, List<XmlSchema> importsList)

       {

           foreach (XmlSchemaImportimport in schema.Includes)

           {

                ICollectionrealSchemas = schemaSet.Schemas(import.Namespace);

                foreach(XmlSchema ixsd in realSchemas)

                {

                    if(!importsList.Contains(ixsd))

                    {

                        importsList.Add(ixsd);

                       AddImportedSchemas(ixsd, schemaSet, importsList);

                    }

                }

           }

       }

       

private voidRemoveXsdImports(XmlSchema schema)

       {

           for (int i = 0; i < schema.Includes.Count; i++)

           {

                if(schema.Includes[i] is XmlSchemaImport)

                   schema.Includes.RemoveAt(i--);

           }

       }

        

void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint,System.ServiceModel.Channels.BindingParameterCollection
bindingParameters)

       {

        //throw new NotImplementedException();

       }

       

void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint,System.ServiceModel.Dispatcher.ClientRuntime
clientRuntime)

       {

           //throw new NotImplementedException();

       }

        

void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint,System.ServiceModel.Dispatcher.EndpointDispatcher
endpointDispatcher)

       {

           //throw new NotImplementedException();

       }

 

void IEndpointBehavior.Validate(ServiceEndpoint endpoint)       

      {           

         //throw new NotImplementedException();       

      }

}

 

 public class MyBehaviorExtension : BehaviorExtensionElement

{

       public overrideType BehaviorType      

     { 

           get { return typeof(MyFlatWsdl);     }

      }

 

protected override object CreateBehavior()

       {

           MyFlatWsdl myBehavior = new MyFlatWsdl();

           return myBehavior;

       }

}

 

Config file changes:

<extensions>
<behaviorExtensions>
<add name="MyEndPointBehavior" type="WcfService2.MyBehaviorExtension, WcfService2"/>
</behaviorExtensions>
</extensions>
 
<service name="WcfService2.Service1">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="" behaviorConfiguration="MyBeh"
name="end" contract="WcfService2.IService1" />
</service>
 
<endpointBehaviors>
<behavior name="MyBeh">
<MyEndPointBehavior />
</behavior>
</endpointBehaviors>
 
With above code/config changes we can easily expose WCF service with Flat WSDL in 4.0.
FYI, in WCF 4.5 it is available as "SingleWSDL" option.
 
Hope this help !

WCF: Simple way to modify serialized response

$
0
0

Problem description

This type of problem generally appears in interop scenarios where client could be .net application and service could be java web service.

  1. .net client application is able to send request.
  2. Java service is able to read the request.
  3. Java service is able to send the response.
  4. However, .net client application is not able to read the response. Client application is just able to read the content as null. Interestingly in fiddler (a web traffic tool) or in netmon (a network monitor tool), we can see actual SOAP payload in response. Question appears why .net is not able to read the payload.

 

 

Issue

It primarily happens due to namespace conflict in xsd-complex-type-elements. In other words, message could not be properly de-serialized to the structure of .net classes. As a best practice, wsdl can be modified. In some cases, .net applications do not have control over web service side (as in vendor).

Solution

From WCF traces as well as SOAP UI tool, we identified the response appears as:

 

 

  • Open response editor for the method in SOAP UI
  • Paste the same content (from WCF traces or use SOAP UI response)
  • Right click on the editor
  • Select Validate
  • Validation is unsuccessful

Note

  • In my case, validation pointed that it has issues with AccountResult node.
  • Applied ns2:AccountResult in place of AccountResult. Validation was successful.

It is safe to claim on payload modification, response can properly be de-serialized in the .net side.

How?

We need to apply code changes in the .net side.

  1. Create a new class CustomInspector (implement IClientMessageInspector) and modify AfterReceiveReply method to correct the anomaly.
 using System.ServiceModel.Dispatcher; 
using System.Xml;
using System.IO;
namespace MyApplication.net
{
public class CustomInspector: IClientMessageInspector
{
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
// Read reply payload
XmlDocument doc = new XmlDocument();
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms);
reply.WriteMessage(writer);
writer.Flush();
ms.Position = 0;
doc.Load(ms);

// Change logic
ChangeMessage(doc);

// Write the reply payload
ms.SetLength(0);
writer = XmlWriter.Create(ms);
doc.WriteTo(writer);
writer.Flush();
ms.Position = 0;
XmlReader reader = XmlReader.Create(ms);
reply = System.ServiceModel.Channels.Message.CreateMessage(reader, int.MaxValue, reply.Version);
}

void ChangeMessage(XmlDocument doc)
{
string xml = doc.OuterXml;
 // Apply the xml modification logic here 
// Replace can be applied as a pure string replacement for string types
xml = xml.Replace("AccountResult", "ns2:AccountResult");
doc.LoadXml(xml);
}

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
return null;
}
}
}

 2.       Create a custom class CustomValidationBehavior (implement IEndpointBehavior) and modify logic for ApplyClientBehavior method.

 using System.Text; 
using System.ServiceModel.Description;
 namespace MyApplication.net 
{
public class CustomValidationBehavior: IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{

}
 public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 
{
clientRuntime.MessageInspectors.Add(new CustomInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
 } 
public void Validate(ServiceEndpoint endpoint)
{
 } 
}
 } 

 3.       Now, we need to associate this custom endpoint behavior with the service proxy instance as in:

 AccountServiceReference.Service1Client proxy = new AccountServiceReference.Service1Client();
proxy.Endpoint.Behaviors.Add(new CustomValidationBehavior());
// Make service method calls
// Get results
 

4.       Client should be able to read the response payload successfully for all nodes. If it has any issues with a particular xml node, we need to identify if any element does not fit in with wsdl defined SOAP namespace.

5.       If the similar situation applies in case of a WCF service where client is java, service can take advantage of custom IDispatchMessageInspector in reverse to IClientMessageinspector.

 

Note: There are certain code formatting challenges in the shared codes above. Please consider the connected blocks of code as a single unit. Keep coding! 

Hope this helps!

 

Created by

Purna Chandra Panda (MSFT)

 


points to note while registering and unregistering COM components

$
0
0

Few points to note while registering and unregistering COM components:

  1. This registry hive (HKEY_CLASSES_ROOT) is a virtual registry hive, which allows for both per-user and per-machine object registration. Per-user COM objects configurations are stored in HKEY_CURRENT_USER\Software\Classes, while per-machine configurations are stored in HKEY_LOCAL_MACHINE\Software\Classes. Typically, per-user configurations take precedence.
  2. Beginning with Windows Vista® and Windows Server® 2008, if the integrity level of a process is higher than Medium, the COM runtime ignores per-user COM configuration and accesses only per-machine COM configuration. Applications that are run-elevated (whether manifested as Require Administrator or user-selected by right-clicking and selecting Run as Administrator), as well as applications run from an account that is a member of the Administrators group where User Account Control (UAC) is disabled, will not be able to access any COM objects configured per-user.
  3. Applications that will require administrator rights should register any dependent COM objects during installation to the per-machine COM configuration store (HKEY_LOCAL_MACHINE\Software\Classes). If an application is run with administrator rights and User Account Control is disabled, the COM runtime ignores the per-user COM configuration and accesses only the per-machine COM configuration. Applications that require administrator rights should register dependent COM objects during installation to the per-machine COM configuration store (HKEY_LOCAL_MACHINE\Software\Classes).

 

References:

https://msdn.microsoft.com/en-us/library/bb756926.aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724475(v=vs.85).aspx

 

WCF: Sending large file to WCF fails with “404 Not Found” Error

$
0
0

 

WCF: Sending large file to WCF fails with “404 Not Found” Error

 

Problem Description

I have a WCF service which accept the file from client but throws an error if the file size is more than 50 MB. If you try to pass a file which has size bigger than 30 MB, you will encounter with following error:

 

 

Demo:

To demonstrate the issue and resolution I created a WCF service with a custom binding as shown below:

 

I will host this service at IIS and will consume it through web application which will be passing files to this service for various sizes. As soon as the size of the service more than 30 MB you will encounter with the error.

Troubleshooting steps:

To understand the root cause of this issue we need to collect following data from WCF service and the client:

1-      WCF traces from client and server where the service is hosted

2-      System.Net traces from the client and server side

After analyzing the traces you will not find the request reaching to WCF service as request claims that service test/service1.svc exists at it records 404. This means request is getting filtered somewhere before to that.

Let’s analyze the client side System.Net traces now. Search for “Exception” in the traces and then track the socket where exception is recorded.

  

Expand the post the request details at line number-198. This will show you the SOAP envelop and complete communication details. This will actually contain an error message that will be in broken strings. When you will compile the broken strings into one you will be able to see this message like shown below:

“Request filtering is configured on the Web server to deny the request because the content length exceeds the configured value.

This is a security feature. Do not change this feature unless the scope of the change is fully understood. You can configure the IIS server to reject requests whose content length is greater than a specified value. If the request's content length is greater than the configured length, this error is returned. If the content length requires an increase, modify the configuration/system.webServer/security/requestFiltering/requestLimits@maxAllowedContentLength setting.”

Below image shows you the error message in System.Net traces.

 

 

Solution:

Once you are able to see the error message in the System.Net traces, you need to review the settings for the maxAllowedContentLength setting. This value can be set at two levels:

1-      IIS Level – This will change the value for all the applications. Default value is 30000000 B.

2-      Application Level (In our case at WCF service level). If you don’t mention this it will be working with default value of IIS 30000000 B.

We will change it at our service so will go for second approach and will declare this value in the web.config as shown below:  

    <system.webServer>

                <security>

                                <requestFiltering>

                                               <requestLimits maxAllowedContentLength="102400000" />

                                </requestFiltering>

                </security>

    </system.webServer>

 Above setting will allow you to upload the files up to 100 MB.

 

Ashutosh Tripathi (MSFT)

Microsoft India

 

 

ASMX: Event code: 3005 : InvalidOperationException : Request format is unrecognized for URL unexpectedly ending in '/URL'.

$
0
0

Issue Definition

ASMX web service hosted over IIS.

Intermittently we observe following error being logged in event viewer.

 

Error In Event viewer:

Event code: 3005 

Event message: An unhandled exception has occurred. 

Event time: 02/03/2015 13:10:11

Event time (UTC): 02/03/2015 16:10:11 

Event ID: c9d437b7eddc4478b6e01d89516d0da1 

Event sequence: 2270182 

Event occurrence: 2481 

Event detail code: 0  

Application information:     

Application domain: /LM/W3SVC/1/ROOT/MyApp-1-130697010076094227     

Trust level: Full      Application Virtual Path: /MyApp     

Application Path: D:\InternetFiles\MyApp\     

Machine name: MYMACHINE  

Process information:     

Process ID: 5160     

Process name: w3wp.exe     

Account name: IIS APPPOOL\ASP.NET v4.0 Classic   

Exception Information:    

Exception type: InvalidOperationException     
Exception message: Request format is unrecognized for URL unexpectedly ending in '/MyURL'.

 at System.Web.Services.Protocols.WebServiceHandlerFactory.CoreGetHandler(Type type, HttpContext context, HttpRequest request, HttpResponse response)

 at System.Web.Services.Protocols.WebServiceHandlerFactory.GetHandler(HttpContext context, String verb, String url, String filePath)

 at System.Web.Script.Services.ScriptHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated)

 at System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig)

 at System.Web.HttpApplication.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()

 at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Request information:    

Request URL: http://XYZ.com/MyApp/MyURL.asmx/MyURL?param=123

Request path: /MyApp/MyURL.asmx/MyURL      

User host address: 192.1.1.1     

 

Solution

After some in depth troubleshooting, we found the problem rooted inside the HttpContext object associated with the incoming request:

Context Info
================================
Address           : 00000004800d64f8
Target/Dump Time  : 3/16/2015 1:34:58 PM
Request Time      : 3/16/2015 1:34:49 PM
Running time      : 00:00:08
HttpContext.Items[]: 0000000480119d58

Request Info
================================
HEAD /MyApp/MyUrl.asmx  <---------------------- PROBLME
Content Length  : -1

Because of VERB as HEAD, we are unable to process the request and eventually end up in writing the event logs.

 

=============
Conclusion:
=============
Some clients like JavaScript and Office use HEAD to probe the resource before sending the request. .asmx is not meant to be used with HEAD so it throws an exception and logs in Event Viewer.

 

Solution:

To resolve we can change the handle for ScriptHandlerFactory to change verb from * (all) to GET,POST only. This lead to IIS returns 404 (not found) and NO error was logged to Event Viewer 

************** Original ***********************
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
</system.web>

***********************************************
************** Modified ********************
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="GET,POST" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
</system.web>
*********************************************

 

Hope this help !

 

Saurabh Somani  - http://blogs.msdn.com/b/saurabs/ 

Rodney Viana      - http://blogs.msdn.com/b/rodneyviana/

WCF: Unable to handle load (SSL and client cert authentication) - MaxPendingAccept limitation

$
0
0

Issue Definition:

WCF unable to handle load from multiple client when running with (Transport security with client credential  as client certificate).

 

Symptoms:

1. From network traces, we see that server takes too much time to send a certificate request...  and eventually the client gives up.

2. Further when the issue happens even the connected clients start observing their request taking lot of time to get processed.

 

 From WCF traces, when the issue was reported

After receiving the Connection information we see the WCF stack waiting for some time to follow the below stack, before error out.

 

at System.ServiceModel.Diagnostics.TraceUtility.TraceEvent(TraceEventType severity, Int32 traceCode, String traceDescription, TraceRecord extendedData, Object source, Exception exception)

at System.ServiceModel.Channels.HttpsChannelListener`1.ValidateAuthentication(HttpListenerContext listenerContext)  <------------------

at System.ServiceModel.Channels.HttpRequestContext.ListenerHttpContext.ValidateAuthentication()

at System.ServiceModel.Channels.HttpRequestContext.ProcessAuthentication()

at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.Authenticate()

at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()

at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)

at System.ServiceModel.Channels.SharedHttpTransportManager.EnqueueContext(IAsyncResult listenerContextResult)

at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult listenerContextResult)

at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)

 

 

So question is what is this method waiting on and why that internal method does not finish in time?

HttpsChannelListener`1.ValidateAuthentication(HttpListenerContext listenerContext)

 

Source code:

public override HttpStatusCode ValidateAuthentication(HttpListenerContext listenerContext)

        {

            HttpStatusCode result = base.ValidateAuthentication(listenerContext);

            if (result == HttpStatusCode.OK)

            {

                if (this.shouldValidateClientCertificate)

                {

                    HttpListenerRequest request = listenerContext.Request;

                    X509Certificate2 certificateEx = request.GetClientCertificate();

                    if (certificateEx == null)  <------------- We end up here and throw the (http://msdn.microsoft.com/en-US/library/System.ServiceModel.Channels.HttpsClientCertificateNotPresent.aspx)

                    {

                        if (this.RequireClientCertificate)

                        {

                            if (DiagnosticUtility.ShouldTraceWarning) <-------------

                            {

                                TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.HttpsClientCertificateNotPresent,

                                    SR.GetString(SR.TraceCodeHttpsClientCertificateNotPresent),

                                    new HttpListenerRequestTraceRecord(listenerContext.Request), this, null);

                            }

                            result = CertificateErrorStatusCode;

                        }

                    }

                 =======

                   Removed the noise

                 =======

            return result;

        }

 

 That brings us to this line of code:

 X509Certificate2 certificateEx = request.GetClientCertificate();

What does this "GetClientCertificate()"  method does.... ?

 

This class is inside the System.Net level

 

 public X509Certificate2 GetClientCertificate() {

            if(Logging.On)Logging.Enter(Logging.HttpListener, this, "GetClientCertificate", "");

            try {

                ProcessClientCertificate();

                GlobalLog.Print("HttpListenerRequest#" + ValidationHelper.HashString(this) + "::GetClientCertificate() returning m_ClientCertificate:" + ValidationHelper.ToString(m_ClientCertificate));

            } finally {

                if(Logging.On)Logging.Exit(Logging.HttpListener, this, "GetClientCertificate", ValidationHelper.ToString(m_ClientCertificate));

            }

            return m_ClientCertificate;

        }

 

 

So now we are trying to call the ProcessClientCertificate() and waiting for this guy to finish.....

As we can see here... System.Net traces gets log appended from this location only.....

where we observe that at a time only 10 GetClientCertRequest are being called from WCF level.

 

 

From System.Net traces I can see following packets:

DateTime=2015-02-15T05:57:06.5407000Z

System.Net.HttpListener Verbose: 0 : [3796] HttpListenerRequest#65752145::GetClientCertificate()

 

Where the GetClientCertificate is started at "05:57:06" and finally we failed at 5:59, so eventually GetClientCert took 2mins... but sometime it may fail quickly.. as well..

 

DateTime=2015-02-15T05:59:06.3487000Z

System.Net.HttpListener Verbose: 0 : [3796] Exiting HttpListenerRequest#65752145::GetClientCertificate()  -> (null)

 

But interesting for sure, as soon as the System.Net level "GetClientCert()" method fails.... WCF will throw the exception and drop the request....

 

 

Assessment

==================

  1. Request which failed at WCF application level, indeed failed at System.Net level when trying to invoke the GetClientCert() and as per the System.Net traces looks like client never send the cert..
  2. Role of MaxPendingAccept at WCF level calling into the System.Net “GetClienCert()”.

 

  

MaxPendingAccepts (in Framework 4.5)

Gets or sets the maximum number of channels a service can have waiting on a listener for processing incoming connections to the service.

The maximum number of channels a service can have waiting on a listener. The default value is 2 * number of processors.

This property limits the number of channels that the server can have waiting on a listener. When MaxPendingAccepts is too low, there will be a small interval of time in which all of the waiting channels have started servicing connections, but no new channels have begun listening. A connection can arrive during this interval and will fail because nothing is waiting for it on the server. This property can be configured by setting the MaxPendingConnections property to a larger number.

https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.connectionorientedtransportbindingelement.maxpendingaccepts(v=vs.110).aspx

 

 

Solution

=================

Interestingly when we moved the app to 4.5 and bumped this value, we see significant improvement in the load handling…

Source code from Framework 4.5, which helps in handling the large load:

http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Channels/SharedHttpTransportManager.cs,eae189be1a91debe

 void StartListening()

        {

            for (int i = 0; i < maxPendingAccepts; i++)

            {

                IAsyncResult result = this.BeginGetContext(true);

                if (result.CompletedSynchronously)

                {

                    if (onCompleteGetContextLater == null)

                    {

                        onCompleteGetContextLater = new Action<object>(OnCompleteGetContextLater);

                    }

                    ActionItem.Schedule(onCompleteGetContextLater, result);

                }

            }

        }

 

Till 4.0 this value is hard coded to 10 and thus we see max request getting executed from System.Net level is only 10.

 

private void StartListening()

{

                for (int i = 0; i < 10; i++)

                {

                                IAsyncResult asyncResult = this.BeginGetContext(true);

                                if (asyncResult.CompletedSynchronously)

                                {

                                                if (this.onCompleteGetContextLater == null)

                                                {

                                                                this.onCompleteGetContextLater = new Action<object>(this.OnCompleteGetContextLater);

                                                }

                                                ActionItem.Schedule(this.onCompleteGetContextLater, asyncResult);

                                }

                }

}

 

 

 

So ideally we don’t have any solution to get rid of above problem until we move to framework 4.5

Another way is to write custom channel and handle the start event.

 

Hope this help !

WCF: Exposing metadata over NetTcp Binding issue

$
0
0

WCF: Exposing metadata over NetTcp Binding issue

 

Problem Description:

You will find your WCF service unresponsive and when you will collect the traces it will show you following exception:

<ExceptionString>System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host

   at System.ServiceModel.Channels.SocketConnection.HandleReceiveAsyncCompleted()

   at System.ServiceModel.Channels.SocketConnection.OnReceiveAsync(Object sender, SocketAsyncEventArgs eventArgs)

</ExceptionString>

<NativeErrorCode>2746</NativeErrorCode>

 

When you will analyze it little more and you will observe that before throwing the above exception you will see following warning thrown by the service. This indicates a throttling is being hit.  

<TraceRecordxmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Warning">

<TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Channels.ServerMaxPooledConnectionsQuotaReached.aspx</TraceIdentifier>

<Description>MaxOutboundConnectionsPerEndpoint quota (10) has been reached, so the connection was closed and not reused by the listener.</Description>

 

Solution:

Service is hosted over IIS and is exposed at netTcpBinding and security is transport security with client credential type as “Windows”.

So what is happening internally, there may be 2 reasons for this failure:

1-      Due to heavy load in the server this MaxOutboundConnectionsPerEndpoint value which is default 10 for netTcpBinding.

2-      Load is not heavy but your client proxies are not releasing the connections.

Let’s believe that client side programming is good and client connections are properly disposed. So we are considering the first scenario and we will write a custom binding to address this issue.

Here is the custom binding that will address this issue:

 

 

Now there are 2 ways to expose the metadata of the service:

1-      Expose it with HTTP mex address with mexHttpBinding

2-      Expose this with netTcp mex address as netTcpBinding

Now, if you expose the metadata over HTTP using system generated binding, it will work fine with IIS hosted environment. As soon as you expose the metadata at netTcpBinding, you will start running into the following issue.

 

 

 

Oops!! What happened?

Let’s check the client side binding and we see we have not updated the service reference after adding new binding. So let’s update it and try again!

First we need to expose the metadata at mexTcpBinding binding and then we need to update the service reference. Our endpoint configuration will look like this.

 

As soon as you will update your service reference you will find the below exception:

 

What is the problem?

Why this failing though I have exposed the service metadata and binding is available. Let’s trace it again:

Here is the exception:

“There is no compatible TransportManager found for URI 'net.tcp://ashu-16.fareast.corp.microsoft.com/Timeout_Demo_Time_Consumer/Service1.svc/Tcp'. This may be because you have used an absolute address that points outside of the virtual application, or the binding settings of the endpoint do not match those that have been set by other services or endpoints. Note that all bindings for the same protocol should have the same settings in the same application”

 

This is happening as we are using the custom binding to expose the service while metadata is still communicating at system provided mexTcpBinding. Though we are using the netTcp transport underneath but we have made little amendments in the basic settings (default settings) of Tcp transport as the value of MaxOutboundConnectionsPerEndpoint.

So we need to use the Custom Binding itself to expose the metadata. So our end point configuration should look like as below:

 

So your client side  app.config will look like as below:

 

 

Now everything works as expected.

Now let’s try another thing. We will try to create another service reference at client app with the net.tcp address url i.e. at

net.tcp://ashu-16.fareast.corp.microsoft.com/Timeout_Demo_Time_Consumer/Service1.svc/Tcp

As soon as you try to add new service reference from your visual studio and give above address to svcuiti.exe you will encounter with following error:

“The URI prefix is not recognized.

Metadata contains a reference that cannot be resolved: 'net.tcp://ashu-16.fareast.corp.microsoft.com/Timeout_Demo_Time_Consumer/Service1.svc/Tcp'.

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:04:59.9440395'.

An existing connection was forcibly closed by the remote host

If the service is defined in the current solution, try building the solution and adding the service reference again.”

 

Let’s trace the server side again:

 

 

Which says “Stream Security is required at http://www.w3.org/2005/08/addressing/anonymous, but no security context was negotiated. This is likely caused by the remote endpoint missing a StreamSecurityBindingElement from its binding.

This exception is appearing as we have used “WindowsStreamSecurity” in custom binding as shown below:

 

 

This security is conflicting with IIS security as SvcUtil.exe runs with no security and IIS asks for a security.

This can be fixed in two ways:

1-      Change the security settings at IIS (highly not recommended as it will start impacting all the applications at IIS)

2-      Expose the metadata at HTTP and create the reference.

So, if you expose the metadata over http and create the reference, it will give you the reference to you. You can force your client to communicate over netTcp once you have metadata available with you.

 

Note: If you host your WCF service as windows service, the net.tcp url will work fine without any issue.

 

Ashutosh Tripathi

Microsoft India

WCF: WCF (xmlSerialization) dropping certain properties of an object during serialization

$
0
0

Task:

To consume the JavaService from a WCF client application.

 

Issue:

WCF Client using XML Serialization dropping certain properties, even though we set them correctly.

 

Tools used to confirm this:

Fiddler traces

 

From WSDL

When we add the service reference via (WSDL file) exposed from Java service we see proxy class methods decorated with XMLSerialization attribute.

Further we also identified that WSDL has set minOccurs attrbute to 0.  When this happens, for every non-string property, there is a corresponding generated property called PropertyNameSpecificed.  So if I have a property name Amount and it is a decimal type, I will have a generated property called AmountSpecified. 

<xs:element minOccurs="0" name="validFrom" type="xs:dateTime"/>

 

When a field/property say myProperty is marked as optional in a SOAP message WCF creates an corresponding extra MyPropertySpecified property that must be set to true when the MyPropertySpecified value is set. Otherwise WCF will not serialize nor send that property

  • In the generated Reference.cs file each optional will have a corresponding IsSpecified property, 

  • like so: 

  • private System.DateTime validFromField

  • private bool validFromFieldSpecified;

 

Solution:

To allow WCF client to perform the correct serialization, we need to set the "IsSpecified" attribute to TRUE on all these properties.

 

I hope this helps !

WCF: Request failing when data pulled in stream is big

$
0
0

Problem Definition:

I have a WCF service "http://localhost:1518/Service1.svc" built on .Net Framework 4.0 and hosted on IIS over a windows server 2008 R2 box. I am pulling data from database using this service. I am encountering with error

"System.ServiceModel.CommunicationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”. "The underlying connection was closed: The connection was closed unexpectedly

I see this problem when data being pulled is more the 4 MB as disc size. As data is transmitted into serialized form so this size actually not the size of the stream instead this is the size of the data when saved into the disc. 

It is also validated that no bad data is transmitted and issue appears whenever the row count pulled from the database is high. 

Analysis: 

For any WCF related issue if the issue can be reproduced on demand, I will strongly recommend to collect verbose level trace as that will collect detailed information about the issue. So here I collected WCF verbose trace and verbose level trace give me information that connection is being closed by the server as shown in exception.

System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly. ---&gt; System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.

 

  

 

 

From this exception I got a clue that server is closing the connection but why and after how much time? 

So I will go ahead and collect following data in parallel. 

1-      Client side WCF + System.Net trace

2-      Server side WCF + System.Net trace 

Below are the settings to enable System.Net and WCF tracing:

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.diagnostics>

    <sources>                                     

      <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" propagateActivity="true" >

        <listeners>

          <add name="xml"/>

        </listeners>

      </source>

      <source name="System.ServiceModel.MessageLogging">

        <listeners>

          <add name="xml"/>

        </listeners>

      </source>

      <source name="System.Net">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

      <source name="System.Net.HttpListener">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

      <source name="System.Net.Sockets">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

      <source name="System.Net.Cache">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

    </sources>

    <sharedListeners>

      <add name="xml"

               type="System.Diagnostics.XmlWriterTraceListener"

                     initializeData="C:\temp\WCFTraces.svclog" />

      <add name="System.Net" type="System.Diagnostics.TextWriterTraceListener"

      initializeData="c:\temp\SNtrace.log" traceOutputOptions = "DateTime" />

    </sharedListeners>

 

    <switches>

      <add name="System.Net" value="Verbose" />

      <add name="System.Net.Sockets" value="Verbose" />

      <add name="System.Net.Cache" value="Verbose" />

      <add name="System.Net.HttpListener" value="Verbose" />

    </switches>

 

  </system.diagnostics>

  <system.serviceModel>

    <diagnostics>

      <messageLogging logEntireMessage="true" logMalformedMessages="true"

          logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />

    </diagnostics>

  </system.serviceModel>

</configuration> 

 

From the client side System.Net traces I searched for the exceptions and got following exceptions:

  

 

Which on expanding will show following details:

 

System.Net.Sockets Verbose: 0 : [5220] Socket#59148624::Receive()

    DateTime=2015-04-23T13:42:56.8466796Z

System.Net.Sockets Verbose: 0 : [5220] Data from Socket#59148624::Receive

    DateTime=2015-04-23T13:42:57.5185546Z

System.Net.Sockets Verbose: 0 : [5220] 00000000 :                                                 :

    DateTime=2015-04-23T13:42:57.5185546Z

System.Net.Sockets Verbose: 0 : [5220] Exiting Socket#59148624::Receive()       -> 0#0

    DateTime=2015-04-23T13:42:57.5185546Z

System.Net.Sockets Verbose: 0 : [5220] Socket#59148624::Dispose()

    DateTime=2015-04-23T13:42:57.5341796Z

System.Net Error: 0 : [5220] Exception in the HttpWebRequest#37711682:: - The underlying connection was closed: The connection was closed unexpectedly.

    DateTime=2015-04-23T13:42:57.5341796Z

System.Net Error: 0 : [5220] Exception in the HttpWebRequest#37711682::GetResponse - The underlying connection was closed: The connection was closed unexpectedly.

 

This means that the exception is recorded when the response was being received by the client and 0 bytes transferred as highlighted.

 Now why this happened?

Let’s trace the service side WCF traces with the timestamp of the System.Net trace. From the timestamp, following exception is of our interest:

  

 

Let’s see the error message of the exception:

 

There was an error while trying to serialize parameter http://tempuri.org/:GetMarketingInfosResult. The InnerException message was 'Maximum number of items that can be serialized or deserialized in an object graph is '65536'. Change the object graph or increase the MaxItemsInObjectGraph quota. '.  Please see InnerException for more details.

 

So is seems this MaxItemsInObjectGraph quotavalue is hitting the limit set by WCF service. Now we need to check this value in the web.config of the service. I am using wsHttpBinding.

 

But I have not set this value anywhere in my web.config, so it should be taking the default value and what is this default value?

 

We see that this default value is set to 2147483647 Bytes for service behaviors as well as for EndPointBehavious.

 

 

 

 So by some reason this default value is not available so this issue is appearing.

Let’s fix this 

Solution:

 

<behaviors>
  <serviceBehaviors>
    <behavior name="LargeServiceBehavior">
      <dataContractSerializer maxItemsInObjectGraph="100000"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

And

<behaviors>
  <endpointBehaviors>
    <behavior name="LargeEndpointBehavior">
      <dataContractSerializer maxItemsInObjectGraph="100000"/>
    </behavior>
  </endpointBehaviors>
</behaviors>

You add these in the <system.serviceModel> element. Don’t forget to set the "behaviorConfiguration" attribute in the configuration of your service or endpoint. And we are done.

Ashutosh Tripathi(MSFT)

Microsoft India


WCF: Not able to download metadata from 3rd party web service

$
0
0

Problem statement

There is a publicly available 3rd party web service. The objective is to consume this service as a normal WCF service client for .net application. However, application gets into error: ‘Cannot obtain metadata using WS-Metadata Exchange or DISCO’. It all happens during metadata download or add service reference option. 

Issue

During the metadata download, you get into error:

C:\Temp>svcutil /t:metadata http://localhost/service1

Microsoft (R) Service Model Metadata Tool

[Microsoft (R) Windows (R) Communication Foundation, Version 4.0.30319.18020]

Copyright (c) Microsoft Corporation.  All rights reserved.

 

Attempting to download metadata from http://localhost/service1' using WS-Metadata Exchange or DISCO.

Microsoft (R) Service Model Metadata Tool

[Microsoft (R) Windows (R) Communication Foundation, Version 4.0.30319.18020]

Copyright (c) Microsoft Corporation.  All rights reserved.

 

Error: Cannot obtain Metadata from http://localhost/service1

 

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: http://localhost/service1

    Metadata contains a reference that cannot be resolved: ‘http://localhost/service1’.

    The content type text/html; charset=utf-8 of the response message does not match the content type of the binding (application/soap+xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: '<pre>Traceback (most recent call last):

<<<<<<Internal callstack of service application>>>>>>

                line 123, in parse

                self.feed(buffer)

                File &quot;/base/data/home/runtimes/python/p'.

 

    The remote server returned an error: (500) Internal Server Error.

HTTP GET Error

    URI: http://localhost/service1

    There was an error downloading 'http://localhost/service1'.

    The request failed with the error message:

--

<?xml version="1.0" encoding="utf-8"?>

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://localhost/service1" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://localhost/service1”>

<<<<Other service wsdl items>>>>

</definitions>

--.

If you would like more help, type "svcutil /?"

 

In any service related cases,

1. Client application should be able to download metadata.

2. After proxy definition of the service is downloaded to the client side, client will form request and dispatch it over the wire.

Over here, it fails at the first step. And, it is clear from the highlighted error.

 

What could be the issue?

If we keenly look into the error, there is a “500 internal server error along with text/html content type”. It means service application is itself broken. Client has no control over service.

Even then, client application looks for a way to consume service. Is it possible?

Answer – Yes

How can it be achieved?

Step-1

1.      Use SOAP UI tool (http://www.soapui.org/)

2.       Consume the web service (In most of the cases, it will work even when there is an issue with service application)

3.       Hit service and see if it works.

4.       In my case, it was successful.

5.       From this step, we are able to identify the HTTP request payload to send for the service request.

Step-2

1.       Prepare the SOAP envelope and convert into XML document.

2.       Create System.Net.HttpWebRequest object and add the metadata information to it.

3.       Read the HttpWebRequest stream and attach SOAP envelope XML to the stream.

4.       Read the System.Net.WebResponse object

5.       Convert webResponse to stream and read the result. However, the result will be a string (i.e. response payload).

Client application code (Console application)

       static void Main(string[] args)        {

            CallService(); 

            Console.ReadLine();

        } 

        private static void CallService()

        {

            var _url = "http://localhost/service1";

            var _action = "http://localhost/service1/GetQuestionsAbout";

             XmlDocument soapEnvelopeXml = CreateSoapEnvelope();

            HttpWebRequest webRequest = CreateWebRequest(_url, _action);

            InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);

             string soapResult;

            using (WebResponse webResponse = webRequest.GetResponse())

            {

                using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))

                {

                    soapResult = rd.ReadToEnd();

                }

                Console.Write(soapResult);

            }

        }

         private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)

        {

            using (Stream stream = webRequest.GetRequestStream())

            {

                soapEnvelopeXml.Save(stream);

            } 

        } 

        private static XmlDocument CreateSoapEnvelope()

        {

            XmlDocument soapEnvelop = new XmlDocument();

            Console.Write("Query for ?? ");

            string queryItem = Console.ReadLine();

             // Pull this xml from SOAP UI or service provider

            soapEnvelop.LoadXml(@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:soap=""http://localhost/service1""><soapenv:Header/><soapenv:Body><soap:GetQuestionsAbout><soap:query>" + queryItem + "</soap:query></soap:GetQuestionsAbout></soapenv:Body></soapenv:Envelope>");

            return soapEnvelop;

        }

         private static HttpWebRequest CreateWebRequest(string url, string action)

        {

            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);

            webRequest.Headers.Add("SOAPAction", action);

            webRequest.ContentType = "text/xml;charset=\"utf-8\"";

            webRequest.Accept = "text/xml";

            webRequest.Method = "POST";

            return webRequest;

        }

 

 

I hope this helps!

 

Identify memory leak for a process hosting ASMX/ WCF service

$
0
0

Problem statement

A good number of asmx web services are hosted on IIS application pool (4.0 | 64bit) over Windows server 2008 R2 SP1. It is observed the private bytes usage for the application pool climbs from 3 to 4 GB in around 1 hour.

Why are there so many allocations in such a quick span of time?

 

How to troubleshoot

Since application is hosted on IIS, the process of interest will be w3wp.exe. We have to treat it as a normal .net process troubleshooting where memory consumption is so high.

Action plan will be to enable perfmon counters for

  • .NET CLR Memory/(*) 
  • Process/(*)
  • .Net CLR Loading/(*)

How to identify if there is any memory leak? (Review)

  • Remove all counters
  • Select .NET CLR Memory/ # Bytes in all Heaps, Process/ Private Bytes counters for the process

The graph appears like below:


 

Observation (from the sampling)

  • Perfmon data has been collected for around 2 hours.
  • We see a pattern where private bytes for w3wp keeps growing at a certain rate. In comparison to it, #Bytes in all heaps graph stays almost flat.
  • It is an indicative where there is a leak in the native modules.

 

Note

Private Bytes:  "The current size, in bytes, of memory that this process has allocated that cannot be shared with other processes."

#Bytes in all heaps: "This counter is the sum of four other counters; Gen 0 Heap Size; Gen 1 Heap Size; Gen 2 Heap Size and the Large Object Heap Size. This counter indicates the current memory allocated in bytes on the GC Heaps."

 

 

How to troubleshoot native memory leak?

We need to get LeakTrack.dll injected memory dumps to troubleshoot further.

Steps

  • Restart the w3wp process
  • Make small number of requests to application
  • Go to debugdiag tool (You can get the latest from http://www.microsoft.com/en-us/download/details.aspx?id=42933)
  • Go to Processes tab
  • Sort the "Process Name" column
  • Find the w3wp (there will be application pool name mentioned in right to identify which w3wp process can be selected)
  • Select the w3wp > Right click > Select "Monitor For leaks"
  • Keep your application testing with high number of requests
  • Monitor the private bytes in debugdiag
  • When size grows to 2.2GB, right click and take a "Full user Memorydump"
  • Second memory dump at 2.6GB size
  • Third memory dump at 3.0GB size
  • Once all dumps are collected, right click process and select "Stop monitoring"

 Review

  • Go to DebuDiag analysis
  • Select MemoryAnalysis only
  • Add Data Files > select the first dump file > Start Analysis

 

  • It will generate reports for the dump file.
  • We have to follow the same process for other 2 memory dumps as well respectively.

 

 

Dump 1

=============================

Number of outstanding allocations = 13,155 allocations (outstanding allocations means x number of allocations are done, but have been not freed up yet from memory)

Total outstanding handle count = 469 handles

Total size of allocations = 1.68 GBytes

Tracking duration = 01:39:09

 

GdiPlus

Module Name  GdiPlus

Allocation Count  1370 allocation(s)

Allocation Size  1.17 GBytes

 

Top function

GdiPlus!GpMemoryBitmap::AllocBitmapData+c2  with 155 allocations takes 1.16GB of memory space

 

Dump 2

============================

Number of outstanding allocations = 13,150 allocations

Total outstanding handle count = 541 handles

Total size of allocations = 2.14 GBytes

Tracking duration = 02:01:34

 

GdiPlus

Module Name  GdiPlus

Allocation Count  1783 allocation(s)

Allocation Size  1.63 GBytes

 

Top function

GdiPlus!GpMemoryBitmap::AllocBitmapData+c2  with 220 allocations takes 1.62GB of memory space 

 

Dump 3

==============================

Number of outstanding allocations = 12,862 allocations

Total outstanding handle count = 493 handles

Total size of allocations = 2.7 GBytes

Tracking duration = 02:26:05

 

GdiPlus

Module Name  GdiPlus

Allocation Count  2283 allocation(s)

Allocation Size  2.19 GBytes

 

Top function

GdiPlus!GpMemoryBitmap::AllocBitmapData+c2  with 290 allocations takes 2.17GB of memory space

 

In dump 3 case, the size of memory dump is 3.16GB. Out of which, 2.19GB GdiPlus module allocations are done in around 2 and half hours.

Now, it is safe to say the overall leak is because of GdiPlus module, but why?

 

Does the web service utilize any GdiPlus APIs for its web methods?

 

Let us identify.

 

How to?

We need to watch for callstacks in the captured memory dumps.

An example:

0:057> kL

 # Child-SP         RetAddr           Call Site

00 00000000`0b99a320 000007fe`fbbfcb6b GdiPlus!GpRecolorObject::ColorAdjust+0x28d

01 00000000`0b99a360 000007fe`fbbfca82 GdiPlus!GpRecolorOp::Run+0x2b

02 00000000`0b99a390 000007fe`fbbf885b GdiPlus!GpBitmapOps::PushPixelData+0x182

03 00000000`0b99a400 000007fe`fbbf7ac8 GdiPlus!GpMemoryBitmap::PushIntoSink+0x267

04 00000000`0b99a530 000007fe`fbafa21b GdiPlus!GpMemoryBitmap::InitImageBitmap+0x290

05 00000000`0b99a600 000007fe`fbafa006 GdiPlus!CopyOnWriteBitmap::PipeLockBitsFromMemory+0xd3

06 00000000`0b99a690 000007fe`fbaff0fa GdiPlus!CopyOnWriteBitmap::PipeLockBits+0x5ea

07 00000000`0b99a810 000007fe`fbb28c23 GdiPlus!GpBitmap::PipeLockBits+0x6e

08 00000000`0b99a840 000007fe`fbb23f75 GdiPlus!GpGraphics::DrvDrawImage+0x287b

09 00000000`0b99b0b0 000007fe`fbb2360b GdiPlus!GpGraphics::DrawImage+0x86d

0a 00000000`0b99b260 000007fe`fbae2a82 GdiPlus!GpGraphics::DrawImage+0xb7

0b 00000000`0b99b2f0 000007fe`fbae2c48 GdiPlus!GdipDrawImageRectRect+0x362

0c 00000000`0b99b3f0 000007fe`f99117c7 GdiPlus!GdipDrawImageRectRectI+0xfc

0d 00000000`0b99b490 000007fe`dd41d439 clr!DoNDirectCall__PatchGetThreadCall+0x7b

0e 00000000`0b99b580 000007fe`dd416da4 System_Drawing_ni!DomainNeutralILStubClass.IL_STUB_PInvoke(System.Runtime.InteropServices.HandleRef, System.Runtime.InteropServices.HandleRef, Int32, Int32, Int32, Int32, Int32,
Int32, Int32, Int32, Int32, System.Runtime.InteropServices.HandleRef, DrawImageAbort, System.Runtime.InteropServices.HandleRef)+0x179

0f 00000000`0b99b6f0 000007fe`dd4e95f9 System_Drawing_ni!System.Drawing.Graphics.DrawImage(System.Drawing.Image, System.Drawing.Rectangle, Int32, Int32, Int32, Int32, System.Drawing.GraphicsUnit, System.Drawing.Imaging.ImageAttributes, DrawImageAbort, IntPtr)+0x264

10 00000000`0b99b850 000007fe`dd418ce1 System_Drawing_ni!System.Drawing.Graphics.DrawImage(System.Drawing.Image, System.Drawing.Rectangle, Int32, Int32, Int32, Int32, System.Drawing.GraphicsUnit, System.Drawing.Imaging.ImageAttributes, DrawImageAbort)+0x99

12 00000000`0b99b960 000007ff`010148fe MyDrawing!MyDrawing.GdiPlusCanvas.BitmapToMonochrome(System.Drawing.Bitmap)+0x2da

13 00000000`0b99ba50 000007ff`01006b5d MyDrawing!MyDrawing.GdiPlusCanvas.GetImageBytes(System.Drawing.Imaging.ImageFormat, Boolean)+0x6e

14 00000000`0b99bad0 000007ff`01006329 MyDrawing!MyDrawing.BaseForm._GetOutput(Drawing.CanvasBase, FormOutputFormat, Int32, Rotation, OutputMode, PdfSettings, Boolean, Boolean)+0xcd

16 00000000`0b99c410 000007ff`00d90392 MyService_Core!MyService.Controller.Create(MyService.Request, MyService.Core.RequestResponse, Account, Boolean, SoftwareID)+0x7da

18 00000000`0b99c6a0 000007ff`00d7c986 MyService!MyService.GetImagesInternal(System.Object, MyService.Core.Request ByRef)+0x38f

19 00000000`0b99c760 000007ff`00d7c7a7 MyService!MyService.WebServiceBase.ExecuteWebMethod[[System.__Canon, mscorlib]](System.Func`1<System.__Canon>, MyService.WebMethodParams)+0x96

1a 00000000`0b99c800 000007fe`f994c9e4 MyService!MyService.GetCommonImages(System.Object)+0xa7

..

4a 00000000`0b99ee50 000007fe`f9adc736 clr!ThreadpoolMgr::WorkerThreadStart+0x3b

4b 00000000`0b99eef0 00000000`773359ed clr!Thread::intermediateThreadProc+0x7d

4c 00000000`0b99feb0 00000000`7756c541 kernel32!BaseThreadInitThunk+0xd

4d 00000000`0b99fee0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d

 

Observation (from callstack above)

1. We see like asmx service APIS call System.Drawing APIs (The System.Drawing namespace provides access to GDI+ basic graphics functionality)

2. It seems graphics APIs like System.Drawing are not supported in asp.net service components. The web link which talks about the same and where alternatives are discussed:

       https://msdn.microsoft.com/en-us/library/system.drawing(v=vs.110).aspx

3. The primary cause of this memory leak is usage of System.Drawing GDI+ APIs in web services.

 

General tips

1. If virtual bytes jump, private bytes stay flat

     => A virtual byte leak i.e. some component is reserving memory but not using it

     => Use debug diag to track it down

2. If private bytes jump but #Bytes in all heaps stay flat

=> Native or loader heap leak.

   => Use debug diag to track it down and/or check if the number of assemblies increase (counter under .net clr loading)

3. #Bytes in all heaps and private bytes follow each other

    => investigate the .net GC heap

 

 

Hope this helps!

 

 

WCF: Non HTTP Activation service installation issue

$
0
0

 

Problem Statement: 

We have a server machine where Net.Pipe Listener Adapter, Net.Tcp Listener Adapter services are deleted while in the server machine these services were running fine. When we observed that these services are disabled, we tried to enable the services but we got a pop up that these services are marked for deletion. Also, it asks the server to be rebooted but being the production server reboot is not possible.  

Analysis: 

As soon as you will try to install these services it will give you errors. Event Logs will show you following logs: 

Event Logs: 

 

<Event Xml:  

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">  

  <System>  

    <Provider Name="Microsoft-Windows-ServerManager" Guid="{8C474092-13E4-430E-9F06-5B60A529BF38}" />  

    <EventID>1616</EventID>  

    <Version>0</Version>  

    <Level>2</Level>  

    <Task>0</Task> 

    <Opcode>0</Opcode>  

    <Keywords>0x4000000000000000</Keywords>  

    <TimeCreated SystemTime="2014-05-20T20:07:31.733425000Z" />  

    <EventRecordID>1182</EventRecordID>  

    <Correlation />  

    <Execution ProcessID="6172" ThreadID="5668" />  

    <Channel>Setup</Channel>  

    <Computer>Ashu-16.fareast.corp.microsoft.com</Computer>  

    <Security UserID="S-1-5-21-4070693332-1989359676-1502584706-1204" />  

  </System>  

  <UserData>  

    <EventXML xmlns:auto-ns3="http://schemas.microsoft.com/win/2004/08/events" xmlns="Event_NS">  

      <message>  

Features:  

.NET Framework 3.5.1 Features  

   Error: Attempt to install Non-HTTP Activation failed with error code 0x80070643.  Fatal error during installation  

   Error: Attempt to install HTTP Activation failed with error code 0x80070643.  Fatal error during installation 

   The following features were not installed:  

      WCF Activation  

      HTTP Activation  

      Non-HTTP Activation

 

Windows Process Activation Service  

   Error: Attempt to install .NET Environment failed with error code 0x80070643.  Fatal error during installation  

   Error: Attempt to install Configuration APIs failed with error code 0x80070643.  Fatal error during installation  

   Error: Attempt to install Process Model failed with error code 0x80070643.  Fatal error during installation  

   The following features were not installed:  

   Process Model  

   .NET Environment  

   Configuration APIs  

</message>  

      <identifiers>221, 222, 223, 41, 219, 218, 217</identifiers>  

    </EventXML>  

  </UserData>  

</Event>  

 

Resolution: 

So it is clear that WCF Non Http Activation installation is failing. Let us try again and try to see the messages that system generates when we try to install these. 

Perform following steps: 

  • Open Control Panel
  • Windows Feature Turn on/Off console
  • Opened Microsoft.Net Framework 3.5.1
  • Non HTTP Activation

 

You will get the following error message immediately. 

Error: You cannot activate this unless you activate Window Process Activation Service 

    • .Net Environment

    • Configuration API

    • Process Model 

So to install the above components follow the steps as shown below: 

  • Reach to Windows Feature Turn on/Off console
  • Window Process Activation Service
  • Check the following components
    • .Net Environment
    • Configuration API
    • Process Model

 

Then, 

  • Open Control Panel and reach to Windows Feature Turn on/Off console-
  • Open Microsoft.Net Framework 3.5.1
  • HTTP Activation
  • Non HTTP Activation 

It will install and enabled the deleted services. Below event log confirms the success.

 

Log Name:      Setup  

Source:        Microsoft-Windows-ServerManager  

Date:          5/29/2014 11:06:54 AM  

Event ID:      1610  

Task Category: None  

Level:         Information  

Keywords:       

User:          FAREAST\astripa  

Computer:      Ashu-16.fareast.corp.microsoft.com 

Description:  

Installation succeeded.  

Features:  

.NET Framework 3.5.1 Features  

   The following features were installed:  

 WCF Activation  
 HTTP Activation  
 Non-HTTP Activation 
 

Windows Process Activation Service  

   The following features were installed:  

   Process Model  

   .NET Environment  

   Configuration APIs 

 

Event Xml:  

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">  

  <System>  

    <Provider Name="Microsoft-Windows-ServerManager" Guid="{8C474092-13E4-430E-9F06-5B60A529BF38}" />  

    <EventID>1610</EventID>  

    <Version>0</Version>

    <Level>4</Level>  

    <Task>0</Task>  

    <Opcode>0</Opcode>  

    <Keywords>0x4000000000000000</Keywords>  

    <TimeCreated SystemTime="2014-05-29T15:06:54.505819800Z" />  

    <EventRecordID>1194</EventRecordID>  

    <Correlation />  

    <Execution ProcessID="6772" ThreadID="7048" />  

    <Channel>Setup</Channel>  

    <Computer>Ashu-16.fareast.corp.microsoft.com</Computer>  

    <Security UserID="S-1-5-21-1708537768-1580818891-725345543-27522" />  

  </System>  

  <UserData>  

    <EventXML xmlns:auto-ns3="http://schemas.microsoft.com/win/2004/08/events" xmlns="Event_NS">  

      <message>  

Features:  

.NET Framework 3.5.1 Features  

   The following features were installed:  

      WCF Activation  

      HTTP Activation  

      Non-HTTP Activation  

Windows Process Activation Service  

   The following features were installed:  

   Process Model  

   .NET Environment  

   Configuration APIs 

 

</message>  

      <identifiers>41, 219, 218, 217, 221, 222, 223</identifiers>  

    </EventXML>  

  </UserData>  

</Event> 

 

So this will install the required services without rebooting the server. Correct steps are mandatory to install the required service.  

Hope this Helps.

 

 

Ashutosh Tripathi (MSFT)

Microsoft (India)

WCF: certificate trust list (CTL) issue with window Server 2012 R2 and Window 8.1

$
0
0

  

 

Problem Description: We have a WCF service https://localhost:38215/Service1.svc . We are accessing this service over SSL and using client certificate for authentication. We are getting 403 Forbidden for Windows Server 2012 R2 and Windows 8.1. The same service runs absolutely fine with Windows Server 2008 R2 and Windows 7 with same certificate and same settings. We are making request to service but not getting the response from there, instead 403 Forbidden is being returned.

Analysis: To understand the issue let collect the WCF+System.Net traces using following settings-

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.diagnostics>

    <sources>

      <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" propagateActivity="true" >

        <listeners>

          <add name="xml"/>

        </listeners>

      </source>

      <source name="System.ServiceModel.MessageLogging">

        <listeners>

          <add name="xml"/>

        </listeners>

      </source>

      <source name="System.Net">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

      <source name="System.Net.HttpListener">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

      <source name="System.Net.Sockets">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

      <source name="System.Net.Cache">

        <listeners>

          <add name="System.Net"/>

        </listeners>

      </source>

    </sources>

    <sharedListeners>

      <add name="xml"

               type="System.Diagnostics.XmlWriterTraceListener"

                     initializeData="C:\temp\WCFTraces.svclog" />

      <add name="System.Net" type="System.Diagnostics.TextWriterTraceListener"

      initializeData="c:\temp\SNtrace.log" traceOutputOptions = "DateTime" />

    </sharedListeners> 

    <switches>

      <add name="System.Net" value="Verbose" />

      <add name="System.Net.Sockets" value="Verbose" />

      <add name="System.Net.Cache" value="Verbose" />

      <add name="System.Net.HttpListener" value="Verbose" />

    </switches> 

  </system.diagnostics> 

  <system.serviceModel>

    <diagnostics>

      <messageLogging logEntireMessage="true" logMalformedMessages="true"

          logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />

    </diagnostics>

  </system.serviceModel>

</configuration>

  

Let’s analyze the traces collected. First we will see SNtrace.log. We see following highlighted warning.

System.Net.HttpListener Warning: 0 : [144] HttpListener#39451090::HandleAuthentication() - Received a request with an unmatched or no authentication scheme. AuthenticationSchemes:Anonymous, Authorization:<null>.

This indicated that service is not able to authenticate the request. Let’s see the WCF trace as this will show us the details about WCF service warning/error. WCF trace reporting a warning “Client certificate is required. No certificate was found in the request.”

 

  

This validates the point that client certificate is not passed to service so service is not authenticating the request. What is the reason this complete set up works for Window 7 and Windows Server 2008 R2 but is failing with Windows 8.1 and Server 2012 R2.

Cause:

When authentication of the client computer is required using SSL or TLS, the server can be configured to send a list of trusted certificate issuers. This list contains the set of certificate issuers which the server will trust and is a hint to the client computer as to which client certificate to select if there are multiple certificates present. In addition, the certificate chain the client computer sends to the server must be validated against the configured trusted issuers list.

Prior to Windows Server 2012 and Windows 8, applications or processes that used the Schannel SSP (including HTTP.sys and IIS) could provide a list of the trusted issuers that they supported for Client Authentication through a Certificate Trust List (CTL).

In Windows Server 2012 and Windows 8, changes were made to the underlying authentication process so that:

  • CTL-based trusted issuer list management is no longer supported.
  • The behavior to send the Trusted Issuer List by default is off: Default value of the SendTrustedIssuerList registry key is now 0 (off by default) instead of 1.
  • Compatibility to previous versions of Windows operating systems is preserved.

But starting from windows 8 and Server 2012, the Schannel implementation will not send server side certificate trust list (CTL) by default.

 

Resolution:

To get this resolved we need to change the settings in the registry as described below: 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL

Value name: SendTrustedIssuerList

DWORD

Set value to 1 to re-enable sending CTL behaviors.

A reboot is required as Schannel change is kernel based and has to rely on reboot taking effect. 

Hope this helps....

 

Ashutosh Tripathi (MSFT)

Microsoft India

WCF: Delegation at Message Level security

$
0
0

 

Basics:

Review this article to get familiar with basic settings needed for WCF delegation.

http://blogs.msdn.com/b/saurabs/archive/2012/08/28/wcf-learning-impersonation-and-delegation.aspx  

 

Basic Message Level security can be easy to set up delegation, as indicated from below diagram:

 

 

What about delegation between boxes with Load Balancer in place ?

 

 

Key points:

1. For Load balancer scenario, we have to be careful because WCF message security deals with "SecurityContextToken" creation and usage.

 

Steps:

Request 1: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue

Response: http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue

Request 2: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT

Response: http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT

Request 3: http://tempuri.org/IService1/GetData

Response: http://tempuri.org/IService1/GetDataResponse

 

Problem:

Because of creation of SCT token, we need to direct the actual call to the same server who issued the SCT to client.

In case we send the SCT token issued from Server 1 to server 2 because of round robin distribution of request via LB, we end up in failure.

 

Approaches attempted and reason for failure:

1. To avoid the SCT creation we can set these two property inside message security tag. This will help us get what we call - ONE SHOT PROXY

a) EstablishSecurityContext

b) NegotialServiceCredential

 

2. Message Security with no Negotiation needs to set the NegotiateServiceCredential = false.

In the case of Windows credentials, setting this property to false causes an authentication based on KerberosToken. 
This requires that the client and service be part of a Kerberos domain. This mode is interoperable with SOAP stacks that implement the Kerberos token profile from OASIS. Setting this property to true causes a SOAP negotiation that tunnels SPNego exchange over SOAP messages. This mode is not interoperable.
Since we set the value to true in the config file, we end up validating the server identity and creating a unique message id .     
 
When NegotiateServiceCredential set to true, EstablishSecurityContext as false.
 
============
Step 1: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
Step 2: http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue
Step 3: http://tempuri.org/IService1/GetData
 
 
When NegotiateServiceCredential set to true along with EstablishSecurityContext as true
======
Step 1: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
Step 2: http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue
Step 3: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT
Step 4: http://tempuri.org/IService1/GetData
 
 
When EstablishSecurityContext is false, we still end up in getting a unique SCT token as a part of SSPI Negotiation (NegotiateServiceCredential  set to true).
        <t:RequestedSecurityToken>
          <c:SecurityContextToken u:Id="uuid-570f65bc-7197-4d56-b388-61a445d317b4-1" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
            <c:Identifier>urn:uuid:20ac8eb5-73f3-46d9-ba43-8c7ea9e8c56b</c:Identifier>
          </c:SecurityContextToken>
        </t:RequestedSecurityToken>
Client end up in using the same Context token it received as a part of SSPI Negotiation.

  
So the true solution is to set both Establish Security context and Negotiate Service Credentials to FALSE.
 
3. But limitation with this approach is, it does not support  client to set TokenImpersonationLevel as "DELEGATION" without which client really can't get a Delegatable token from DC.
Above approach is good, if we just need to authenticate or impersonate the cred to next hop.. and no requirement to do delegation.
Failure Code:
public KerberosSecurityTokenProvider(string servicePrincipalName, TokenImpersonationLevel tokenImpersonationLevel, NetworkCredential networkCredential)
        {
            if (servicePrincipalName == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("servicePrincipalName");
            if (tokenImpersonationLevel != TokenImpersonationLevel.Identification && tokenImpersonationLevel != TokenImpersonationLevel.Impersonation)  <-------------------------------------
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("tokenImpersonationLevel",
                    SR.GetString(SR.ImpersonationLevelNotSupported, tokenImpersonationLevel)));
            }
 
            this.servicePrincipalName = servicePrincipalName;
            this.tokenImpersonationLevel = tokenImpersonationLevel;
            this.networkCredential = networkCredential;
        }
 
Stack Trace:
Server stack trace: 
   at System.IdentityModel.Selectors.KerberosSecurityTokenProvider..ctor(String servicePrincipalName, TokenImpersonationLevel tokenImpersonationLevel, NetworkCredential networkCredential)
   at System.ServiceModel.ClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement, Boolean disableInfoCard)
   at System.ServiceModel.ClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
   at System.ServiceModel.Security.SecurityProtocol.AddSupportingTokenProviders(SupportingTokenParameters supportingTokenParameters, Boolean isOptional, IList`1 providerSpecList)
   at System.ServiceModel.Security.SecurityProtocol.OnOpen(TimeSpan timeout)
   at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)

 

3. Another approach is to user "KerberosOverTransport" security mode via custom binding. But again it does not allow client to set the Token Impersonation level as Delegation.

4. If we try to move to - "TransportWithMessageCredential" security mode, SSL handshake will happen and further we will still end up in creating the SCT token.

Request 1: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue

Response: http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue

Request 2: http://tempuri.org/IService1/GetData

c:SecurityContextToken [ u:Id=uuid-fa4f216a-18cf-4204-b4a0-11a62fe765a4-1 xmlns:c=http://schemas.xmlsoap.org/ws/2005/02/sc ]

Response: http://tempuri.org/IService1/GetDataResponse

  

Solution:

1. There is only one solution: Enable Sticky session on LB to make sure specific client are routed to same machine all the time and we can live with default Message security or even TransportWithMessageCred..

2. Switch to pure transport security and windows authentication.

Viewing all 164 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>