Sharepoint guidance v2 – drop 9
This week, we published the results of interation 9 to our codeplex site.
You can get it here:
In this drop, we have addressed a number of tasks:
- Implemented trusted facade pattern and removed the fake SSO provider
- Refactored the repositories to make better use of WCF Proxies
- Support for UpdatePanel in SafeScriptManager
- Updated PartnerLandingPage
- Removed most usages of .net 3.5
- Provided instructions on how to use a host name to access extranet site
Trusted facade pattern
We are demonstrating in our RI how to call back-end services from SharePoint. It’s quite common to have different credentials to log on to back end services.
Replacing the fake SSO provider
Before, we were using a fake SSO provider (Single Sign On) for that. We built a fake SSO provider because it’s actually quite hard and complex to build a real SSO provider. Since the SSO provider should store passwords in a secure way, there are a whole range of attacks you need to watch for. We felt we didn’t want to take on that extra complexity in our project, so we built a fake SSO provider that stored the passwords in clear text. We hoped that calling it ‘fake’ would make it clear enough that this is not something you would want to do in production.
We a lot of feedback that giving an example that shows how to store passwords in clear text is bad. No matter how clearly you explain that it’s not something you want to do in production, somebody is going to do it anyway. But since didn’t want to show you how to build a real SSO provider (that would be a project in itself), we decided to change our implementation to a trusted facade.
Trusted facade explained
The following diagram shows the trusted facade pattern:
A user authenticates with the trusted facade. It validates the credentials provided by the user. Then, if the trusted facade calls the back end service on behalf of the user, it only specifies the username. The back end service trusts the Trusted Facade to provide the correct username, so it doesn’t need to perform any authentication.
We implemented our trusted facade based on this MSDN article. Our implementation looks like this:
A user connects to SharePoint either through windows authentication or through Forms Based Authentication (FBA). Then, when the user wants to make a request to a backend system, for example to retrieve the price for a product, the pricing repository will find out what partner the user belongs to. It will then call the back end service with the name of the partner. The pricing service trusts our SharePoint application to provide the correct partner name, so it doesn’t require any passwords.
Of course, you have to make sure that only the account that SharePoint runs under is allowed to access the pricing service.
We took a critical look at our current implementation of the repositories.
The goal of the repositories is to hide data access logic from consumers. For example, we have a ProductCatalogRepository, which has methods like: GetProduct(string sku) to retrieve product information. This repository uses the BDC for some of it’s methods, but for other, it calls into our productcatalog webservices directly. However, the consumers of these repositories don’t know where the data comes from. They also don’t know (and don’t care) that the data is cached.
Adding a reference to a webservice is very simple in Visual Studio. What happens under the covers is quite a bit more complex. Visual studio will generate proxy classes based on the metadata that’s returned from the service.
We implemented the following best practices for calling web services:
- If your service references are used by multiple projects, create a single project that holds the service references and reference that project.
There are to reasons for this. If you are making changes to your webservice, you only have to update one service reference. Forgetting to update one can cause annoying bugs. But from a design perspective, if you generate two proxies for the same web service, then you’ll have duplicate (incompatible) types in your system. For example, the price object generated for proxy 1 will be different from the price object generated for proxy 2. Even though they have exactly the same signature, you can’t reuse the types for them or reuse methods that work on them. We implemented this in the Contoso.Pss.Services.Client solution.
- Don’t call the service proxies directly, but wrap the calls to the service proxies into repositories or service agents.
This best practice is used to shield your application from (minor) changes to the service. It does take some extra coding, because you have to transform the objects you get back from the service into objects that can be used by your application. So this practice does adds a level of indirection and extra complexity to your application, so you have to make the tradeoff if the extra complexity is worth the isolation. In general, if the services are created for and only used by your application, you typically don’t need such a level of indirection. However, if you don’t have control over your services or other clients are also using the services, it’s often worth it.
There were a couple of area’s we explicitly didn’t look at.
Getting the repositories from the service locator
Before, we were creating the repositories directly in our code, for example in our presenters. This is often undesirable, because it makes the presenters harder to unit test. Now, we have registered the repositories in our service locator. Therefore, we can use the service locator to get instances of our repositories and we are able to mock out these in our unit tests. Sweet :)
UpdatePanel in sharepoint
Removed most .net 3.5 usages
We were making judicious use of the wonderful new features of .Net 3.5 such as Linq queries, lambda expressions and type initializers. However, we got the feedback from our advisors that .net 3.5 is not widely used by the sharepoint developer community. After many discussions, we agreed that removing most of the .net 3.5 usages would make our guidance a bit more consumable by the sharepoint developer community.
Added instructions on how to use a host name to access extranet site
Lastly, we added some instructions on how to use a host name to access extranet sites. Now, our extranet site is accessable on localhost:9001. If you would prefer to host the extranet site on a hostname, for example extranet.mydomain.com, we have included instructions on how to do that.