Welcome to my blog, stay tunned :
Home

.NET 4

OData CRUD in SharePoint 2013 + Authentication scheme explanation

Hi,

A while ago, I wrote a blog post about OData and recorded a video that shed some light on how to use one of the most unused built-in factory of SharePoint 2010.
This example was explaining how to leverage OData to query data stored in memory but it only demonstrated the "R" of CRUD operations. Before reading further this post, if you're not familiar with hosting WCF Data Services in SharePoint, I'd really recommend you to read my previous post since I won't go into details anymore.
In SharePoint 2010, this was quite difficult to implement because in many scenarios, the authentication providers associated with the web applications are still based on windows integrated security. When coming to data update. As described on MSDN, the article on WCF Services in SharePoint Foundation explains that the authentication scheme (anonymous/ntlm/kerberos) is added by SharePoint Foundation 2010 to the URL (and to the ID of the returned entities) to uniquely identity resources when multiple authentication protocols are enabled for a single webapp...(example anonymous/kerberos).
So far so good but what MSDN doesn't explain is that because of this, only the R of CRUD is working....To illustrate that, I've written a very basic service that is exactly the same between 2010 and 2013 but you'll see that the behavior is slightly different. This demo service allows to handle a list of courses with the support of CRUD operations. I'll share the code a bit later but first let's see how this service reacts on SharePoint 2010.
When calling it from the browser, you get this:

As you can see, the authentication scheme is indeed part of the URL... Therefore, if you try to perform an update from a server-side consumer component, say a console app for which you've added a service reference to /_vti_bin/ODataCRUD.svc, you get the following :

Because as you can see, the URL used to target the object we want to update contains NEGOCIATE...and this results in the highlighted error.
Despites of the fact that the very promising class attribute [ServiceFactoryUsingAuthSchemeInEndpointAddress(UsingAuthSchemeInEndpointAddress = false)] exists, it has, at the time of writing absolutely no effect on the WCF service behavior...meaning that the above error persists.
So, except consuming a custom OData service for update/delete via AJAX (with AJAX, you generate the URLS manually), I never managed to get it working from server-side component consuming the WCF service via a proxy. Of course, working with HttpWebRequest works :













HttpWebRequest req = HttpWebRequest.Create("http://server/_vti_bin/ODataCRUD.svc/Courses(ID)") as HttpWebRequest;
req.Method = "MERGE";
req.Credentials = System.Net.CredentialCache.DefaultCredentials;
req.ContentType = "application/json";
byte[] data = UTF8Encoding.UTF8.GetBytes("{ \"CourseTitle\" : \"Updated Course\" }");
req.ContentLength = data.Length;
Stream DataStream=req.GetRequestStream();
DataStream.Write(data, 0, data.Length);
DataStream.Close();
req.GetResponse();

Leveraging .NET 4 in SharePoint 2013 Series (7) - WCF REST Caching

Hi,
I'll be writing a series of blog posts about leveraging .NET 4 within SharePoint 2013. As you might know already, SharePoint 2013 is now based on this .NET runtime version v4.0.30319 which actually allows developers to benefit from .NET 4 features. You couldn't do that with SharePoint 2010 which was still based on .NET runtime v2.0.50727.

AspNetCacheProfile

WCF 4 brings a new caching mechanism that is built on top of ASP.NET caching. One can easily use that in the context of SharePoint 2013. Say that you want to build a service that returns the latest news of the company on the form of either ATOM XML, either RSS.

Say that these news are the results of an aggregation that takes time to complete, you'd likely want to cache that in order to avoid to perform costly operations whenever someone sends a request to visualize those news.

With WCF 4, it's a piece of cake and the good news is that, it's not much more complicated to integrate that in SharePoint 2013. Indeed, two things must be done:

  • Define cache profiles in the web.config
  • <caching>
    <outputCacheSettings>
      <outputCacheProfiles>
        <add name="CompanyNewsFeed" 
          duration="3600" 
          varyByHeader="Accept"
          varyByParam="" />
      </outputCacheProfiles>
    </outputCacheSettings>
    </caching>
    

    The drawback you have here is that you must define this in the web.config of the SharePoint web app you are targeting. You can't define the caching section in a custom web.config that you would deploy along with your .svc file because this section can only be defined in the root web.config. So, you'd either see with your administrators, either write some piece of code with SPWebConfigModification (automatic but sometimes dangerous), either you document the change and let the administrators cope with it.
    The best would have been of course to deploy a custom web.config file along with your service so that nothing needed to be changed but I couldn't succeed unless I convert the ISAPI (_vti_bin) virtual directory as an application but that's not something you want to do in SharePoint, right?.
    Anyway, above I'm just declaring a cache profile that retains data during 1 hour. So, any subsequent request after the first request will pull the data from the cache unless the Accept header changes. In the case of RSS/ATOM, this will change according to the choice you make.

  • Decorate your service methods with the AspNetCacheProfile attribute and specify the cache profile you want to use
  • For sake of simplicity, I'm not going to follow the WCF best pracitces (Contract/Service/DataContract) and I'm not making any error handling to make it short and focus on the caching story. I'm sure you'll forgive me :). So, I've assembled everything in those two following classes:

    //Data object
    public class News
    {
        public string Title;
        public string Body;
        public string Author;
        public DateTime PublishedDate;
        public News() { }
    }
    
    //Service Attributes
    [ServiceContract]
    [ServiceKnownType(typeof(Atom10FeedFormatter))]
    [ServiceKnownType(typeof(Rss20FeedFormatter))]
    [AspNetCompatibilityRequirements(
      RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]    
    [System.ServiceModel.ServiceBehavior(
      IncludeExceptionDetailInFaults = true)]
    public class NewsService 
    {
      [OperationContract]
      //This is where you make the link to the cache profile you defined earlier in the web.config
      [AspNetCacheProfile("CompanyNewsFeed")]        
      [WebGet(UriTemplate = "/news/feed/{format}")]
      public SyndicationFeedFormatter GetCompanyNews(string format)
      {
        //Here I'm just building a dummy list of news but
        //in the real world, this could be a heavy operation
        List<News> DummyNews = new List<News>();
        for (int i = 0; i < 4; i++)
        {
          DummyNews.Add(new News
          {
             Title = string.Concat("News ",i),
             Body = string.Concat("This is the fake news number ",i),                    
             PublishedDate = DateTime.Now
          });
        }
        //Building the returned feed    
        SyndicationFeed ReturnedNews = new SyndicationFeed            
        {
          Title = new TextSyndicationContent("Company News"),
          Description = new TextSyndicationContent("Company Feed"),
          Items = from NewsItem in DummyNews
                  select new SyndicationItem
                  {
                    Title=new TextSyndicationContent(NewsItem.Title),
                    Content=new TextSyndicationContent(NewsItem.Body),                                                      
                    PublishDate=NewsItem.PublishedDate
                  }
        };
    
        if(format == "atom")
          return ReturnedNews.GetAtom10Formatter();
        else
          return ReturnedNews.GetRss20Formatter();
        }
    }
    
    

So, the result looks like this:

and if you look at the date & time, it won't change during 1 hour unless you decide to change the format (atom or rss). Last thing I should add even if it's obvious, since this WCF caching capability relies on ASP.Net caching, it's not distributed. This means that in the context of SharePoint where you usually have several WFE, each WFE will have its own cache state. This could lead to troubles for more sensitive data if the load balancer redirects your request randomly to any WFE, you could have different states unless you're using sticky sessions.

Happy Coding!

Leveraging .NET 4 in SharePoint 2013 Series (6) - WCF WebFaultException

Hi,

I'll be writing a series of blog posts about leveraging .NET 4 within SharePoint 2013. As you might know already, SharePoint 2013 is now based on this .NET runtime version v4.0.30319 which actually allows developers to benefit from .NET 4 features. You couldn't do that with SharePoint 2010 which was still based on .NET runtime v2.0.50727.

WebFaultException

Leveraging .NET 4 in SharePoint 2013 Series (5) - .AsParallel()

Hi,

I'll be writing a series of blog posts about leveraging .NET 4 within SharePoint 2013. As you might know already, SharePoint 2013 is now based on this .NET runtime version v4.0.30319 which actually allows developers to benefit from .NET 4 features. You couldn't do that with SharePoint 2010 which was still based on .NET runtime v2.0.50727.

.AsParallel()

Leveraging .NET 4 in SharePoint 2013 Series (4) - Parallel.ForEach

Hi,

I'll be writing a series of blog posts about leveraging .NET 4 within SharePoint 2013. As you might know already, SharePoint 2013 is now based on this .NET runtime version v4.0.30319 which actually allows developers to benefit from .NET 4 features. You couldn't do that with SharePoint 2010 which was still based on .NET runtime v2.0.50727.

Parallel.ForEach

Leveraging .NET 4 in SharePoint 2013 Series (3) - SortedSet

Hi,

I'll be writing a series of blog posts about leveraging .NET 4 within SharePoint 2013. As you might know already, SharePoint 2013 is now based on this .NET runtime version v4.0.30319 which actually allows developers to benefit from .NET 4 features. You couldn't do that with SharePoint 2010 which was still based on .NET runtime v2.0.50727.

SortedSet

SortedSet is a new collection allowing you to optimize sorting. Let's take a basic example of it. Say you want to sort lists of a given SharePoint site alphabetically. Up to now, you would have done probably like this:

Leveraging .NET 4 in SharePoint 2013 Series (2) - Lazy Loading

I'll be writing a series of blog posts about leveraging .NET 4 within SharePoint 2013. As you might know already, SharePoint 2013 is now based on this .NET runtime version v4.0.30319 which actually allows developers to benefit from .NET 4 features. You couldn't do that with SharePoint 2010 which was still based on .NET runtime v2.0.50727.

Lazy Loading

Lazy Loading in .NET 4 allows to defer the instantitiation on an object until it is actually being used. It can be particularly useful in scenarios involving heavy objects consuming a lof of resources.

Leveraging .NET 4 in SharePoint 2013 Series (1) - Tuples

Hi,

I'll be writing a series of blog posts about leveraging .NET 4 within SharePoint 2013. As you might know already, SharePoint 2013 is now based on this .NET runtime version v4.0.30319 which actually allows developers to benefit from .NET 4 features. You couldn't do that with SharePoint 2010 which was still based on .NET runtime v2.0.50727.

Tuples