Archive for the ‘Windows Communication Foundation (WCF)’ Category

Using the ULS Viewer for your custom application

January 8, 2012

The ULS Viewer is a wonderful tool that all SharePoint admins absolutely should have on their servers. There is no other utility that is as quick and easy to use for ULS log viewing – and more importantly, it’s free!

I am helping develop some custom Remote Blob Storage services for SQL Server 2008 and SharePoint 2010 (Stepwise Enterprise Storage – imminent release!) and I wanted to be able to use the ULS log viewer, but I didn’t want to spam the SharePoint logs and our services don’t need to be installed on SharePoint itself.

I set up the Microsoft Enterprise Library Logging Application Block and the Rolling Flat File Trace Listener to do the job for me. The rolling flat file trace listener automatically creates a new file when the current file meets certain criteria, such as size or age.  Note the hard-coded [fileName=”MyService-20200101-0000.log”], this is required because the ULS Log Viewer is hard-coded to look for files matching the format *-????????-?????.log i.e. MyService-yyyymmdd-HHmmss.log. You can set this to something different, but I thought this would be fairly safe.

First I added a Rolling Flat File Trace Listener:

<add name="Rolling Flat File Trace Listener"
fileName="MyService-20200101-0000.log"
footer=""
formatter="ULS SingleLine Text Formatter"
header=""
rollFileExistsBehavior="Increment"
rollInterval="Day"
rollSizeKB="2048"
timeStampPattern="-yyyyMMdd-HHmm"
traceOutputOptions="None"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
filter="All"
type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>

then I need to make sure the format for the output was correct. ULS wants the following fields supplied:

•Timestamp: Equivalent to the “TimeGenerated” field in the “Application” event Log

•Process: the image name of the process logging its activity followed by its process ID (PID) between parentheses.

•TID: Thread ID

•Area: This maps the “Source” field in the “Application” event Log

•Category: this maps the “Category” field in the “Application” event Log

•EventID: A unique internal Event ID (which you can generate)

•Level: Logging level i.e. Information, Verbose, Error, etc.

•Message: Text message

•Correlation: may contain a link to the the EventID of another logged event, which again you can generate

so this is the formatter I used:

<add
template="{timestamp(local:dd/MM/yyyy HH:mm:ss.fff)} {tab}{appDomain} {tab}{win32ThreadId} {tab}{source} {tab}{category} {tab}{eventid} {tab}{severity} {tab}{message} - {priority} - {dictionary({key} - {value}|)}"           
type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"           
name="ULS SingleLine Text Formatter" />

Example WCF system.serviceModel web.config sections

April 21, 2010

This post is to illustrate an example system.serviceModel section in a web.config for WCF .NET 3.5. The system.serviceModel section of your web.config allows you to set security, bindings, endpoints, and behaviors. There is an almost overwhelming number of configuration items you can choose, particularly if you are trying to set up security. Sometimes it is useful to have a reference to use, so I’m hoping this post will help people fix their own web.config issues.

This service is exposed via SOAP, REST and metadata and illustrates some basic settings to use for the system.serviceModel entry.

 <system.serviceModel>

<!– use the bindings section when you are building a client to connect to a web service, not when you are creating the service –>
  <bindings />
<!– use the client section when you are building a client to connect to a web service, not when you are creating the service –>
  <client />
<!– the services section allows you to define WCF services –>

  <services>

<!– this service definition is a basic WCF service. Full stops have been added for readability –>
   <service name=”my.service” behaviorConfiguration=”my.behavior.configuration” >
       
        <!– SOAP endpoint –>

<!–

This exposes your service via SOAP

The contract element must match your service contract [ServiceContract] interface

The binding defines the type of service as a WCF service which supports transactions, reliable services, and so on. basicHttpBinding is another common binding to use here.

–>
    <endpoint address=”” binding=”wsHttpBinding” contract=”my.IContract”>
    </endpoint>

        <!– REST endpoint –>

<!–

This exposes your service via REST – see the behavior configuration for more info – note the different binding type of webHttpBinding. This is new in WCF with .NET 3.5SP1, and specifies the REST interface.

Note the use of the “address” element. This is needed to differentiate itself from the SOAP binding above, so SOAP requests would be accessed via (for example) http://server.local/my.service/ and REST requests would use http://server.local/my.service/rest/ i.e. the address element is appended to the service url. If you have the address elements the same for REST and SOAP, WCF will throw a config error.

–>
        <endpoint address=”rest” binding=”webHttpBinding” contract=”my.IContract” behaviorConfiguration=”Endpoints.RESTBehavior”>
        </endpoint>

        <!– mex endpoint –>

<!– metadata information –>
        <endpoint address=”mex” binding=”mexHttpBinding” contract=”IMetadataExchange”/>
       
   </service>
  </services>
  <behaviors>
   <serviceBehaviors>
        <!– WCF Service Behaviors –>
    <behavior name=”my.behavior.configuration”>
          <serviceThrottling maxConcurrentSessions=”100″/>
     <!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
     <serviceMetadata httpGetEnabled=”true”/>
     <!– To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information –>
     <serviceDebug includeExceptionDetailInFaults=”true”/>
    </behavior>
   </serviceBehaviors>
 
      <!– WCF Endpoint Behaviors –>
      <endpointBehaviors>
        <behavior name=”Endpoints.RESTBehavior”>
          <webHttp/>
        </behavior>
      </endpointBehaviors>

    </behaviors>
 </system.serviceModel>

WCF REST Url Request Returns a 404 Error

November 19, 2009

This error occurs because IIS is doing the right thing as far as it knows, and WCF wants more! Background – WCF REST implementations allow you to expose web service methods via url mappings. For example, a server “myservice.svc” has a method “Test”. This could be accessed by the url http://theserver/myservice.svc/Test in a standard web browser. WCF automatically maps the url to the appropriate web service method and returns the results. This is incredibly useful for testing when you just want to get some web service results to view the data, and works well with applications/technologies (like json and silverlight) that can access data via urls rather than having to use SOAP.

The problem for me occurred when trying to deploy my new services to a test server. The services installed fine, I could view the WSDL from the auto-generated WCF metadata, but as soon as I requested a web service method I got a 404 error. After some serious research and pulling bits from MSDN, forum postings, IIS logs, and way too much trial-and-error, the trick seems to be to ensure that the .svc mapping in IIS does not try and validate the url. It should just pass the work over to WCF. To check this:

1. Open IIS admin console
2. Open your services virtual directory/application properties
3. In Application Settings, click Configuration
4. On the Mappings tab, in the Application Mappings section, locate and highlight the .svc entry and click the Edit button
5. Ensure the “Check that file exists” check-box is *not* checked
6. Click OK
7. Restart IIS (stopping the website doesn’t appear to be enough)

This should fix the problem! By ticking the “Check that file exists” box, you are instructing IIS to validate the URL before it passes off to the mapped application. Because the URL  http://theserver/myservice.svc/Test doesn’t actually exist, IIS dutifully returns a 404 error. By un-ticking this box, IIS will just make sure the .svc file exists, then hand off to the aspnet_isapi.dll to do its WCF magic.

Note that if you can’t view the metadata for your service, there are other problems to check as well, like making sure .NET Framework 3.5 is installed, your web app uses .NET 2.0 instead of .NET 1.1, and that your configuration file is correct.

HTH someone save a week like I just spent finding out what was wrong!

HOWTO: Fix WCF Host Name on IIS

March 24, 2009

This is a problem I have tripped across before, and it just popped up again.  Time for a post on how to fix it, mainly so I won’t have to track down MSDN articles and obscure posts to remember how to do it!

When building a WCF Web Service on your local machine, the service will automatically generate WSDL for you with an address similar to http://YOURPC/MyService.svc.  This works fine when testing locally, but when you want to publish this to your production environment so it can be used by World + Dog, it doesn’t respect the fact you have a nice URL you would like to use instead.  For example, if your production server is “Server01” and the URL you have assigned to the website in IIS is my.publicserver.com, your service may look like this:
WCF Service, wrong URL

Instead of displaying the “real” URL (my.publicserver.com), it displays the name of the server (server01) instead. Not at all what is required! Worse still, connections to your web server will fail because the WSDL is pointing to the non-published server name and your client won’t be able to get there.  This is because WCF automatically uses the IIS Site Bindings to determine what the base addresses for the service should be.

The solution is to update the IIS metabase so IIS knows what to do with the request, then WCF will pick up on this. To fix this, perform the following steps.

Get the Website Identifier from IIS

To change the site bindings you need to know which site to change.  Open the IIS Manager to view the sites available, find the one you want to change, and record the website id in the “Identifier” column.  You will need this in the next step.
IIS Manager

Change the IIS Site Bindings
The format of an IIS site binding is “<ip>:<port>:<hostname>”. For HTTP, the default site binding for the default web site is “:80:”. The service gets messages from any IP addresses for the host and it uses “weak” wildcard for address registration. It needs to be the same as the same host name for the site so that it shows up in your service base address. The IIS utility tool adsutil.vbs (or appcmd.exe on IIS7) is used to modify the IIS metabase entries.
View your current site bindings using the example below.

NOTE – YOU MUST USE YOUR WEBSITE IDENTIFIER.

cscript.exe //NoLogo %systemdrive%\inetpub\adminscripts\adsutil.vbs get W3SVC/your_website_identifier_here/ServerBindings

and, for SSL/secure connections, use the following to view the current site bindings:

cscript.exe //NoLogo %systemdrive%\inetpub\adminscripts\adsutil.vbs get W3SVC/your_website_identifier_here/SecureBindings

To change the site bindings, modify the “get” to a “set” and put in your domain name to link to as per the following example:

cscript.exe //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/your_website_identifier_here/ServerBindings “:80:my.publicserver.com”

For HTTPS:

cscript.exe //nologo %systemdrive%\inetpub\adminscripts\adsutil.vbs set W3SVC/your_website_identifier_here/SecureBindings “:443:my.publicserver.com”

Reset the App Pool
When the IIS settings have been changed, WCF will not automatically pick up the changes from the IIS Metabase until the AppDomain has been restarted. Do this via:

  • Changing/resaving the web.config file for the virtual application (you don’t need to actually change the file, as long as it is saved so .NET picks up the change and restarts the app domain)
  • Run “iisreset.exe”
  • Restart the server

All Fixed!
This should complete the changes. When you query the WCF service again, the base address should be correct.

WCF Service, Right URL

WCF Talking to SharePoint Web Services

November 12, 2008

This had nailed me for about 3 days – how to get a Windows Communication Foundation-based call to a SharePoint 2007 Web Service.  Thankfully, there is a solution:

http://blah.winsmarts.com/2008-7-Using_a_WCF_Client_to_talk_to_SharePoint_OOTB_Web_Services.aspx

In particular, I was using:

<security mode=TransportCredentialOnly>
<transport clientCredentialType=Ntlm/>
</security>

in my app.config, which I think was the issue.  Replacing that with:

<security mode=TransportCredentialOnly>
<transport clientCredentialType=Ntlm proxyCredentialType=Ntlm realm=“”/>
<message clientCredentialType=UserName algorithmSuite=Default/>
</security>

and the code change as specified in the blog post fixed everything!  Once again, I am a victim of not knowing enough about WCF security configuration *sigh*  Annoyingly, some web service calls worked, and some didn’t, which made it more difficult to spot the issue.  These worked:

  • SiteData (GetSiteAndWeb)
  • Lists (GetList)

but this one (my important one!) didn’t:

  • Lists (GetListItems)

After I made the config change, all worked perfectly.

 

UPDATE: Two more items to add to this post, the first in particular because I kept on getting exceptions all wrapped up in a FaultException:

“Exception of type ‘Microsoft.SharePoint.SoapServer.SoapServerException’ was thrown.” 

This was particularly annoying because I couldn’t work out any way to get the underlying exception information.

  1. Adding this line fixed my FaultException problem :
    sharepointServiceClient.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
  2. Make sure you set the Endpoint address to the site you want to interrogate.  Usually this means adding a line similar to:
    listsClient.Endpoint.Address = new EndpointAddress(webInfo.SiteUrl + “/_vti_bin/lists.asmx”);
    otherwise you will probably just get FaultExceptions / SoapServerExceptions and not be able to work out why!