• Shortcuts : 'n' next unread feed - 'p' previous unread feed • Styles : 1 2

» Publishers, Monetize your RSS feeds with FeedShow:  More infos  (Show/Hide Ads)


Date: Monday, 03 Mar 2014 17:34

Die BASTA! Spring ist rum, und wieder einmal war es super. Danke an die Organisierer und natürlich an die Teilnehmer!

Hier sind die Folien zu meinen Vorträgen:


Zu den Ganztages-Workshops am Montag und Freitag gibt es naturgemäß keine Folien Winking smile

Für den Freitags-Workshop “End-to-End-Implementierung einer Cross-Platform Modern Business Application” gibt es hier das “laufende” GitHub-Repository, in das Ingo Rammer und ich während des Tages immer hinein ge-psuhed haben.

https://github.com/thinktecture/basta-endtoend

 

Viel Spaß!

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Friday, 24 May 2013 09:54

Come and join me Oct 30-31, 2013 in Oslo for a two days hands-on course organized by ProgramUtvikling.

ASP.NET Web API & SignalR: lightweight web-based architectures for you!"

Time for change: whether it is a classic desktop application, a public or internal web site or a variety of mobile apps - customers and end-users long for multiple ways to access and work with data and processes. Web-based architectures, patterns and techniques can make the life of software architects and developers considerably easier in the face of these requirements.

Description:
Let's face it! The current trends and developments especially in the area of mobile platforms & devices and cloud computing will cause a re-thinking in architectural aspects for many software projects and products. If you ignore this today you may be in big trouble tomorrow. How can I reach a plethora of users and client devices? How can I integrate my systems and application parts in a lightweight and interoperable manner? How am I able to push data in near-real-time fashion from my services to my clients?
This course tries to answer these and more questions. Christian Weyer will show you in a pragmatic way how to face the new challenges. See all of this coming to life by using technologies and frameworks like ASP.NET Web API, SignalR, .NET- and HTML5/JavaScript-based clients - mobile or not.

 

More information at the ProgramUtvikling web site.
See you there!

 

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Tuesday, 30 Apr 2013 12:47

Ingo and I just published a new book chapter of our henriquat.re online (continuously deployed) ebook.
The topic this time is about properly integrating SignalR hubs with your AngularJS applications to realize near realtime push communication. For web browser, desktop or mobile apps.

"Pushing Data: Integrating With ASP.NET SignalR Hubs"

In modern applications the end users want to get their data. They want it now, they want it up-to date. In fact it does not matter whether these are pure web application, native desktop installations or mobile apps: everybody wants his data now!

For .NET-minded developers there are a numbers of options to implement near-real-time push style communication from the server/the services to the clients/consumers. You can choose plain HTTP or the super-new WebSockets features available in .NET 4.5 together with Windows 8 and Windows Server 2012. But the coolest and increasingly popular approach is to use a new framework: ASP.NET SignalR.

While it is not intended- and surely beyond the scope of this ebook - to give an introduction or even deep dive into SignalR, we need to have a look at some concepts and code in order to realize a smooth integration of SignalR and AngularJS.

The final goal of this chapter is to have an AngularJS-style integration of calling and listening to server-side SignalR push services.

 

Enjoy!

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Thursday, 21 Mar 2013 09:31

OK, here we go:

'Introducing SignalR: Push Services with Hubs' - my first (introductory) Pluralsight course is now live!
Push Baby!

I am already planning the next one on SignalR – so, more to come...

Author: "Christian Weyer"
Send by mail Print  Save  Delicious 
Date: Thursday, 14 Mar 2013 18:03

Brock has done an amazing job and added CORS (Cross-Origin Resource Sharing) support for ASP.NET Web API. He is now an official contributor to the ASP.NET stack - great!

Head over to his blog to see more details.

 

BTW: there is a very good explanation & description of how to use the feature in the Wiki.

Author: "Christian Weyer"
Send by mail Print  Save  Delicious 
Date: Monday, 04 Mar 2013 08:17

Erst einmal nochmals vielen lieben Dank an alle, die in meine beiden Breakout Sessions und meinen Ganztages-Workshop in Darmstadt gekommen sind!

Da ich ja in meinen beiden Sessions keine "wirklichen" Foliensätze verwendet hatte sondern Demos und Code gezeigt habe, gibt es dieses Mal nix zum Downloaden ;) Beim Workshop war es ja genauso - interaktiv!

Hier aber die versprochenen Links zum Code & den Demos:

Danke und bis bald.

 

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Tuesday, 29 Jan 2013 08:35

There have been a couple of people asking for a sample how to host the ‚non-visual' parts of thinktecture IdentityServer v2 outside of IIS & ASP.NET. E.g. in a Windows or a Console (no, not really…) application.

Here on GitHub you will find a very simple simple PoC which hosts the OAuth2 token endpoint. That said, it is obviously by no means feature complete.
This endpoint uses ASP.NET Web API and thus self-hosting is kinda piece of cake.

namespace SelfHostConsoleHost
{
    internal class SelfHostServer
    {
        private HttpSelfHostServer selfHost;

        [Import]
        public IConfigurationRepository ConfigurationRepository { get; set; }

        public async void Start(string baseAddress)
        {
            var httpConfig = new HttpSelfHostConfiguration(baseAddress);

            Database.SetInitializer(new ConfigurationDatabaseInitializer());

            Container.Current = new CompositionContainer(new RepositoryExportProvider());
            Container.Current.SatisfyImportsOnce(this);

            ProtocolConfig.RegisterProtocols(httpConfig, ConfigurationRepository);

            selfHost = new HttpSelfHostServer(httpConfig);

            await selfHost.OpenAsync();
        }

        public async void Stop()
        {
            if (selfHost != null)
            {
                await selfHost.CloseAsync();
            }
        }
    }
}

As said, it just offers one endpoint:

namespace SelfHostConsoleHost
{
    public class ProtocolConfig
    {
        public static void RegisterProtocols(HttpConfiguration httpConfiguration, IConfigurationRepository configuration)
        {
            // necessary hack for now - until the DI implementation has been changed
            var a = Assembly.Load("Thinktecture.IdentityServer.Protocols");
 
            var clientAuthConfig = CreateClientAuthConfig();

            httpConfiguration.MessageHandlers.Add(new RequireHttpsHandler());

            if (configuration.OAuth2.Enabled)
            {        
                httpConfiguration.Routes.MapHttpRoute(
                    name: "oauth2token",
                    routeTemplate: Thinktecture.IdentityServer.Endpoints.Paths.OAuth2Token,
                    defaults: new { controller = "OAuth2Token" },
                    constraints: null,
                    handler: new AuthenticationHandler(clientAuthConfig, httpConfiguration)
                );
            }
        }
 
        public static AuthenticationConfiguration CreateClientAuthConfig()
        {
            var authConfig = new AuthenticationConfiguration
            {
                InheritHostClientIdentity = false,
                DefaultAuthenticationScheme = "Basic",
            };

            // accept arbitrary credentials on basic auth header,
            // validation will be done in the protocol endpoint
            authConfig.AddBasicAuthentication((id, secret) => true, retainPassword: true);
 
            return authConfig;
        }
    }
}

Again: the code is here: Self-Hosted IdentityServer v2 PoC

Hope this helps.

Author: "Christian Weyer" Tags: ".NET, Architecture, Distributed Applicat..."
Send by mail Print  Save  Delicious 
Date: Tuesday, 29 Jan 2013 07:41

OK, I think a couple of you guys already did it successfully – others just look for something written. Here we go.

Let's start right away by browsing to GitHub and clone the IdentityServer.v2 repo:

After cloning we have the following code structure in Windows Explorer:

Open Thinktecture.identityServer.sln as an elevated admin (for the Windows Azure Compute Emulator to work correctly). Build the entire solution.

No, choose Add… New project… and add a new Cloud project to the solution.

In the Cloud Service dialog do not choose any new project, just hit OK.

We now add the existing IdSrv WebSite project as a Web Role to the Windows Azure project, just like so:…

For now, the solution should look something like this:

Alright. On to some essential Cloud stuff now.

We need an SSL certificate. I am going to use an existing self-issued cert from my local machine. This of course needs to be a 'real' certificate if you deploy IdSrv as a production STS to Windows Azure – of course

Please head over to WebSite role configuration and the Certificates tab. Specify your desired certificate:

Based on this certificate we now create an SSL endpoint:

OK, this should be it for now.

Let's attack the database side of things. We need a SQL database for our identity configuration and data. I am going to create a new one via the Windows Azure management portal:

Please make a note of the connection string for your SQL database as we still need to change the connection strings inside IdentityServer's configuration files.

Then open up connectionString.config in the Configuration folder inside the WebSite project and adjust the connection strings to point to your SQL database in the Cloud:

 

<connectionStrings>
    <add name="IdentityServerConfiguration"
    connectionString="Server=tcp:….database.windows.net,1433;
    Database=idsrvcloud;User ID=christian@…;Password=...;
    Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
    providerName="System.Data.SqlClient" />

    <add name="ProviderDB"
    connectionString="Server=tcp:….database.windows.net,1433;
    Database=idsrvcloud;User ID=christian@…;Password=...;
    Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
    providerName="System.Data.SqlClient" />
</connectionStrings>

… drum roll …

F5 (with the Cloud project as the startup project) and pray …

Enter the basic setup information you need to enter and you should be good to go. This locally running instance inside Windows Azure Compute Emulator already uses the Cloud SQL database – just for the records.

Done… well almost … I am spilling the beans already now so that we can save some cycles.

There is an issue with the Membership hash algorithm type on Cloud VMs.

  • Locally: HMACSHA256
  • Azure Cloud Emulator: HMACSHA256
  • Published to Cloud Service: SHA1

So it looks like there must some machine.config setting in Cloud Service images – Microsoft is investigating this.

For us it means we need to set the keys explicitly in web.config (you can use a tool like this):

<system.web>
    <machineKey
        decryptionKey="46CD6B691..."
        validationKey="EC4752081..."
        decryption="AES"
        validation="HMACSHA256" />
...

OK.

After that we need to export the SSL cert, anyways, so that we can upload it to the Cloud Service , e.g. via the management portal.

And then, we finally can publish & deploy to Windows Azure:

After approx. 8 to 10 minutes we have our thinktecture IdentityServer v2 running up in the Cloud.

Hope this helps.

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Test post   New window
Date: Tuesday, 29 Jan 2013 07:35

From WLW 2012.

Author: "Christian Weyer"
Send by mail Print  Save  Delicious 
Date: Monday, 05 Nov 2012 15:43

Our thinktecture IdentityServer version 2 will be a very different and very powerful identity beast!

Dominick already talked quite a bit about the features and how to use them. And Brock is surely at it as well.

Today I will show how to use IdentityServerv2 to implement the OAuth2.0 implicit grant flow as outlined in the official OAuth2 spec – and we are going to use a JavaScript client for that.

For the sake of a little bit of mobile-ness I am going to use KendoUI Mobile to have a native looking mobile UI (which you could then combine e.g. with Cordova/PhoneGap to create a native app).

We are going to look to secure a super novel and world overtaking… TODO app Smile

1


Admittedly, this is only the basic gist of what an app should look like and feature-wise we will focus on the OAuth part today.
First let’s head to IdentityServer an create a new OAuth Client like this:

idsrv1


One important part of the configuration is the callback/redirect URI. This is where the IdP sends us the token to.

In addition, we need a relying party/resource we can use to create tokens for and which will accept these tokens coming from our JavaScript clients.

idsrv2


Alright, time to jump on to the client side.
I try to encapsulate my JS code as much as possible. One nice pattern to get a basic structure is MVVM and KendoUI has good support for that.

The page above for the Start tab has a viewmodel which does just fire up the OAuth process (in this case the authentication):

   1:  var startViewModel = kendo.observable({
   2:      openLoginView: function () {
   3:          oauth2ViewModel.openAuthWindow(
   4:             endpoints.IdpOauthEndpointUrl);
   5:      }
   6:  });
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


The OAuth viewmodel holds the token and offer methods to kick off the login process and parse the token from the return URL.

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
   1:  var oauth2ViewModel = kendo.observable({
   2:      token: "",
   3:      
   4:      openAuthWindow: function () {
   5:          var url = endpoints.IdpOauthEndpointUrl + "?" 
   6:             + $.param(oAuthConfig);
   7:          window.open(url, "Login", "height=500,width=350");
   8:      },
   9:      
  10:      loginCallback: function (params) {
  11:          this.token = params["access_token"];
  12:          window.kendoMobileApplication.navigate("#todosPage");
  13:      }
  14:  });
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


In order to craft the correct URL for IdentityServer we need a couple of parameters which need to correspond to what we previously set up in IdSrv for the OAuth client and the RP (see the IdSrv screenshots above):

   1:  var endpoints = {
   2:      IdpOauthEndpointUrl: "https://localhost/idsrv/issue/
   3:         oauth2/authorize"
   4:  };
   5:   
   6:  var oAuthConfig = {
   7:      client_id: "tt_tudus",
   8:      scope: "http://tt.com/mobile/todos",
   9:      response_type: "token",
  10:      redirect_uri: "http://localhost/simpletudus/
  11:         oauthcallback.html"
  12:  }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


Alright. Let’s look at the flow now.
Once we clicked on Login a new window pops up which loads the IdentityServer login page:

2


After loging into IdSrv we get the resource consent page and choose to allow access:

3


IdSrv will now send the token to callback URL specified earlier in the IdSrv config.

This URL looks something like this:

http://localhost/simpletudus/oauthcallback.html#access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI…
&token_type=urn:ietf:params:oauth:token-type:jwt&expires_in=35999


The code of the oauthcallback.html page is pretty simple. It parses the token from the hash (#) part of the URL and fires an event on the calling page to pass over the token (see the Google OAuth developers page for more details on the process):

   1:  <script src="js/libs/jquery-1.7.1.min.js" type="text/javascript"></script>
   2:  <script src="js/libs/jquery.ba-bbq.min.js" type="text/javascript"></script>
   3:   
   4:  <script type="text/javascript">
   5:      //var params = {}, queryString = location.hash.substring(1),
   6:      //    regex = /([^&=]+)=([^&]*)/g, m;
   7:   
   8:      //while (m = regex.exec(queryString)) {
   9:      //    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  10:      //}
  11:      
  12:      var params = $.deparam.fragment(
  13:         location.hash.substring(1));
  14:      
  15:      window.opener.oAuthCallback(params);
  16:      window.close();    
  17:  </script>
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


Note
: I am using jQuery BBQ in the above code to parse the URL, the commented code shows how to do it without any external library.

In the main page we have some kind of a proxy event handler which just passes the token on to the above shown OAuth viewmodel:

   1:  <script>
   2:      function oAuthCallback(params) {
   3:          oauth2ViewModel.loginCallback(params);
   4:      }
   5:  </script>
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


In the OAuth viewmodel login callback method we then simply set the token and trigger navigation to the TODO items page.

When hitting the refresh button in the upper left side of the Items view the actual call to the resource is made with standard jQuery. This happens in the loadTodos call:

   1:  var todosViewModel = kendo.observable({
   2:      todosSource: new kendo.data.DataSource(
   3:         { sort: { field: "title", dir: "asc" } }),
   4:      
   5:      loadTodos: function () {
   6:          var self = this;
   7:   
   8:          dataservices.getTodos(oauth2ViewModel.token)
   9:              .done(function (data) {
  10:                  self.todosSource.data(data);
  11:              });
  12:      }
  13:  });
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


The data services logic is embedded in its own ‘class’ and simply uses the token acquired before to set the appropriate Bearer Authorization header before making the jQuery GET request against the TODO items resource (which is implemented with ASP.NET Web API, BTW):…

   1:  var dataservices = (function () {
   2:      function beforeSend(xhr, token) {
   3:          xhr.setRequestHeader("Authorization", 
   4:             createBearerHeader(token));
   5:      }
   6:   
   7:      function createBearerHeader(token) {
   8:          var header = "Bearer " + token;
   9:          return header;
  10:      }
  11:   
  12:      return {
  13:          getTodos: function (token) {
  14:              return $.ajax({
  15:                  url: endpoints.ServiceEndpointUrl,
  16:                  type: "get",
  17:                  dataType: "json",
  18:                  beforeSend: function (xhr) { beforeSend(xhr, token); }
  19:              });
  20:          }
  21:      };
  22:  }());
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }


And voila…:

4


So please head to GitHub and get the IdSrv bits and give us feedback – thanks!


The entire code for this complete end-to-end sample can be found on GitHub.

Hope this helps.

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Friday, 12 Oct 2012 07:29

The Beta version of our open source IdentityServer STS has been released today:

http://leastprivilege.com/2012/10/12/thinktecture-identityserver-v2-beta/

 

Check out the short intro video to get a quick start:

http://leastprivilege.com/2012/10/12/setup-thinktecture-identityserver-v2-in-7-minutes/

 

Any feedback is always welcome and highly appreciated! Dominick and Brock (and a little bit of myself will hang out there…)
https://github.com/thinktecture/Thinktecture.IdentityServer.v2/issues

 

Thanks.

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Saturday, 06 Oct 2012 08:48

The other day I was building an integration layer for native HTML5/JS-based mobile apps with Windows Azure’s ACS. For that I needed to craft a redirect URL in one of the action in a controller called AcsController.

This is my route setup for Web API:

   1:  config.Routes.MapHttpRoute(
   2:      name: "ACSApi",
   3:      routeTemplate: "api/acs/{action}/{ns}",
   4:      defaults: new { controller = "Acs", ns = RouteParameter.Optional, 
   5:          realm = RouteParameter.Optional }
   6:  );
   7:   
   8:  config.Routes.MapHttpRoute(
   9:      name: "DefaultApi",
  10:      routeTemplate: "api/{controller}/{id}",
  11:      defaults: new { id = RouteParameter.Optional }
  12:  );
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

Then in the controller action I try to use Url.Link to build a redirect URL:

var redirectUrl = Url.Link("ACSApi", new { controller = "Acs", action = "Noop" });

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

On various systems running .NET 4.0 this call returned null. Including Windows Azure Web Sites. On installations with .NET 4.5 all was fine. After several emails back and forth with the Web API team in Redmond it turned out that there is a bug in .NET 4.0.

The issue is in ASP.NET Routing with routes that have optional route values followed by a slash. This issue has been fixed in .NET 4.5. But there is a workaround for 4.0 like this:

   1:  config.Routes.MapHttpRoute(
   2:      name: "ACSApi",
   3:      routeTemplate: "api/acs/{action}/{ns}",
   4:      defaults: new { controller = "Acs", ns = RouteParameter.Optional, 
   5:          realm = RouteParameter.Optional }
   6:  );
   7:   
   8:  config.Routes.MapHttpRoute(
   9:      name: "ACSApi2",
  10:      routeTemplate: "api/acs/{action}/{ns}/{realm}",
  11:      defaults: new { controller = "Acs", realm = RouteParameter.Optional }
  12:  );
  13:   
  14:  config.Routes.MapHttpRoute(
  15:      name: "DefaultApi",
  16:      routeTemplate: "api/{controller}/{id}",
  17:      defaults: new { id = RouteParameter.Optional }
  18:  );
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

Hope this helps.

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Monday, 24 Sep 2012 07:45

Wie in meinen Vorträgen, in der Keynote und im Panel versprochen, hier nun die Slides und Demos zu meinen Auftritten auf der BASAT! 2012.

  • Für jedermann: Leichtgewichtige Services-Architekturen mit Web-APIs
  • Leicht gemacht: Push-Kommunikation mit SignalR
  • Messaging mit .NET für jedermann – in der Cloud und lokal: Windows [Azure | Server] Service Bus
  • Mobile und Cloud: Apps und Devices mit, in und über Windows Azure verbinden

 

Vielen Dank an alle, die in den Vorträgen waren – und Danke an die Organisatoren der BASTA!

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Tuesday, 18 Sep 2012 13:59

The Windows Azure Service Bus and the Access Control Service (ACS) are good friends – buddies, indeed.

Almost all official Windows Azure Service Bus-related demos use a shared secret approach to authenticate directly against ACS (although it actually is not an identity provider), get back a token and then send that token over to the Service Bus. This magic usually happens all under the covers when using the WCF bindings.

All in all, this is not really what we need and seek for in real projects.
We need the ability to have users or groups (or: identities with certain claims) authenticate against identity providers that are already in place. This IdP needs to be federated with the Access Control Service which then in turn spits out a token the Service Bus can understand.

Wouldn’t it be nice to authenticate via username/password (for real end users) or via certificates (for server/services entities)?

Let’s see how we can get this working by using our thinktecture IdentityServer. For the purpose of this blog post I am using our demo IdSrv instance at https://identity.thinktecture.com/idsrv.

The first thing to do is to register IdSrv as an identity provider for the respective Service Bus ACS namespace. Each SB namespace has a so called buddy namespace in ACS. The buddy namespace for christianweyer is christianweyer-sb. You can get to it by clicking the Access Control Service button in the Service Bus portal like here:

image

In the ACS portal for the SB buddy namespace we can then add a new identity provider.

image

image

thinktecture IdentityServer does support various endpoints and protocols, but for this scenario we are going to add IdSrv as a WS-Federation-compliant IdP to ACS. At the end we will be requesting SAML token from IdSrv.

image

The easiest way to add it to ACS is to use the service metadata from https://identity.thinktecture.com/idsrv/FederationMetadata/2007-06/FederationMetadata.xml

Note: Make sure that the checkbox is ticked for the ServiceBus relying party at the bottom of the page.

image

Next, we need to add new claims rules for the new IdP.

Let’s create a new rule group.

image

I am calling the new group IdSrv SB users. In that group I want to add at least one rule which says that a user called Bob is allowed to open endpoints on my Service Bus namespace.

image

In order to make our goal, we say that when an incoming claim of (standard) type name contains a value Bob then we are going to emit a new claim of type net.windows.servicebus.action with the Listen value. This is the claim the Service Bus can understand.
Simple and powerful.

image

We could now just add a couple more rules here for other users or even X.509 client certificates.

Before we can leave the ACS configuration alone we need to enable the newly created rule group on the ServiceBus relying party:

image

… and last but not least I have to add a new relying party configuration in Identity Server for my SB buddy namespace with its related WRAP endpoint:

image

Done.

For using the external IdP in my WCF-based Service Bus applications I wrote a very small and simpler helper class with extension methods for the TransportClientEndpointBehavior. It connects to the STS/IdP requesting a SAML token which is then used as the credential for the Service Bus.

 

using System;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Security;
using Microsoft.IdentityModel.Protocols.WSTrust;
using Microsoft.IdentityModel.Protocols.WSTrust.Bindings;
using Microsoft.ServiceBus;

namespace ServiceBus.Authentication
{
    public static class TransportClientEndpointBehaviorExtensions
    {
        public static string GetSamlTokenForUsername(
           this TransportClientEndpointBehavior behavior, string issuerUrl, string serviceNamespace, 
           string username, string password)
        {
            var trustChannelFactory =
                new WSTrustChannelFactory(
                    new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
                    new EndpointAddress(new Uri(issuerUrl)));

            trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
            trustChannelFactory.Credentials.UserName.UserName = username;
            trustChannelFactory.Credentials.UserName.Password = password;

            try
            {
                var tokenString = RequestToken(serviceNamespace, trustChannelFactory);
                trustChannelFactory.Close();

                return tokenString;
            }
            catch (Exception ex)
            {
                trustChannelFactory.Abort();
                throw;
            }             
        }       

        public static string GetSamlTokenForCertificate(
           this TransportClientEndpointBehavior behavior, string issuerUrl, string serviceNamespace, 
           string certificateThumbprint)
        {
            var trustChannelFactory =
                new WSTrustChannelFactory(
                    new CertificateWSTrustBinding(SecurityMode.TransportWithMessageCredential),
                    new EndpointAddress(new Uri(issuerUrl)));

            trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
            trustChannelFactory.Credentials.ClientCertificate.SetCertificate(
                StoreLocation.CurrentUser,
                StoreName.My,
                X509FindType.FindByThumbprint,
                certificateThumbprint);

            try
            {
                var tokenString = RequestToken(serviceNamespace, trustChannelFactory);
                trustChannelFactory.Close();            

                return tokenString;
            }
            catch (Exception ex)
            {
                trustChannelFactory.Abort();
                throw;
            }                
        }

        private static string RequestToken(string serviceNamespace, WSTrustChannelFactory trustChannelFactory)
        {
            var rst =
                new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue, 
                   WSTrust13Constants.KeyTypes.Bearer);
            rst.AppliesTo = new EndpointAddress(
                String.Format("https://{0}-sb.accesscontrol.windows.net/WRAPv0.9/", serviceNamespace));
            rst.TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml2TokenProfile11;

            var channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
            var token = channel.Issue(rst) as GenericXmlSecurityToken;
            var tokenString = token.TokenXml.OuterXml;

            return tokenString;
        }
    }
}

 

Following is a sample usage of the above class. .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

static void Main(string[] args)
{
    var serviceNamespace = "christianweyer";
    var usernameIssuerUrl = 
       "https://identity.thinktecture.com/idsrv/issue/wstrust/mixed/username";

    var host = new ServiceHost(typeof(EchoService));

    var a = ServiceBusEnvironment.CreateServiceUri(
        "https", serviceNamespace, "echo");
    var b = new WebHttpRelayBinding();
    b.Security.RelayClientAuthenticationType =
        RelayClientAuthenticationType.None; // for demo only!
    var c = typeof(IEchoService);

    var authN = new TransportClientEndpointBehavior(); 
            
    var samlToken = authN.GetSamlTokenForUsername(
        usernameIssuerUrl, serviceNamespace, "bob", ".......");
                        
    authN.TokenProvider =
        TokenProvider.CreateSamlTokenProvider(samlToken);

    var ep = host.AddServiceEndpoint(c, b, a);
    ep.Behaviors.Add(authN);
    ep.Behaviors.Add(new WebHttpBehavior());

    host.Open();
    Console.WriteLine("Service running...");

    host.Description.Endpoints.ToList()
        .ForEach(enp => Console.WriteLine(enp.Address));

    Console.ReadLine();
    host.Close();
}
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

And the running service in action (super spectacular!)

image


Hope this helps!

Author: "Christian Weyer" Tags: ".NET, Architecture, Azure, Distributed A..."
Send by mail Print  Save  Delicious 
Date: Monday, 03 Sep 2012 20:48

Danke an alle, die live bei der DOUG mit dabei waren – und vorab auch an alle, die sich die Aufnahme ansehen werden Smile

Hier sind wie angekündigt die Slides und das Live Coding Beispiel. Weitere Samples findet man direkt im Signal Code auf GitHub.

 

Bis bald!

Author: "Christian Weyer" Tags: ".NET, Architecture, Azure, Distributed A..."
Send by mail Print  Save  Delicious 
Date: Monday, 04 Jun 2012 07:42

The official word on changes from Beta to RC for Web API-related topics (filtered from the original page).

  • ASP.NET Web API now uses Json.NET for JSON formatting: The default JSON formatter in ASP.NET Web API now uses Json.NET for JSON serialization. Json.NET provides the flexibility and performance required for a modern web framework.
  • Formatter improvements: The methods on MediaTypeFormatter are now public to enable unit testing of custom formatters. A single formatter can now support multiple text encodings. UseBufferedMediaTypeFormatter to implement simple synchronous formatting support.FormatterContext has been removed. To get access to the request from a formatter on the server implement GetPerRequestFormatterInstance.
  • Removed System.Json.dll: Because of the overlap with functionality already in Json.NET the System.Json.dll assembly has been removed.
  • XmlMediaTypeFormatter uses DataContractSerializer by default: The XmlMediaTypeFormatternow uses the DataContractSerializer by default. This means that by default ASP.NET Web API will use the Data Contract programming model for formatting types. You can configure theXmlMediaTypeFormatter to use the XmlSerializer by setting UseXmlSerializer to true.
  • Formatters now always handle the body content: ASP.NET Web API formatters are now used consistently for handling both the request and response content. We have removedIRequestContentReadPolicy. The FormUrlEncodedMediaTypeFormatter class has been updated to use MVC-style model binding, so you can still use model binding infrastructure for handling form data in the request body.
  • HTTP content negotiation decoupled from ObjectContent: Previously in ASP.NET Web API all HTTP content negotiation logic was encapsulated in ObjectContent, which made it difficult to predict when HTTP content negotiation would occur. We have decoupled HTTP content negotiation from ObjectContent and encapsulated it as an IContentNegotiator implementation.ObjectContent now takes a single formatter. You can run HTTP content negotiation whenever you want using the DefaultContentNegotiator implementation to select an appropriate formatter.IFormatterSelector has been removed
  • Removed HttpRequestMessage<T> and HttpResponseMessage<T>: Previously there were two ways to specify a request or response with an ObjectContent instance: you could provide anObjectContent instance directly, or you could use HttpRequestMessage<T> orHttpResponseMessage<T>. Having two ways of doing the same thing complicated request and response handling, so HttpRequestMessage<T> and HttpResponseMessage<T> have been removed. To create content negotiated responses that contain an ObjectContent use the CreateResponse<T>extension methods on the request message. To send a request that contains an ObjectContent use the PostAsync<T> extension methods on HttpClient. Or, use the PostAsJsonAsync<T> andPostAsXmlAsync<T> extension methods to specify a request that will be specifically formatted with as JSON or XML respectively.
  • Simplified action parameter binding: You can now predictably determine whether an action parameter will be bound to the request body. This ensures that the request stream is not unnecessarily consumed. Parameters with simple types by default come from the URL. Parameters with complex types by default come from the body. There can be only one body parameter. You can explicitly specify if a parameter comes from the URL or from the body using the [FromUri] and[FromBody] attributes.
  • Query composition is now implemented as a reusable filter: Previously support for query composition was hard coded into the runtime. Query composition is now implemented as a reusable filter that can be applied as an attribute ([Queryable]) to any action that returns anIQueryable instance. This attribute is now required to enable query composition.
  • Cookies: The HttpRequestMessage and HttpResponseMessage classes expose the HTTP Cookie and Set-Cookie headers as raw strings and not structured classes. This made it cumbersome and error prone to work with cookies in ASP.NET Web API. To fix this we introduced two newCookieHeaderValue and CookieState that follow RFC 6265 HTTP State Management Mechanism. You can use the AddCookies extension method to add a Set-Cookie header to a response message. Use the GetCookies extension method to get all of the CookieHeaderValues from a request.
  • HttpMessageInvoker: The HttpMessageInvoker provides a light weight mechanism to invoke anHttpMessageHandler without the overhead of using HttpClient. Use HttpMessageInvoker for unit testing message handlers and also for invoking message handlers on the server.
  • Response buffering improvements: When web-hosting a web API the response content length is now set intelligently so that responses are not always chunked. Buffering also enables reasonable error messages to be returned when exceptions occur in formatters.
  • Independently control IHttpController selection and activation: Implement theIHttpControllerSelector to control IHttpController selection. Implement IHttpControllerActivator to control IHttpController activation. The IHttpControllerFactory abstraction has been removed.
  • Clearer integration with IoC containers that support scopes: The dependency resolver for ASP.NET Web API now supports creating dependency scopes that can be independently disposed. A dependency scope is created for each request and is used for controller activation. Configuring dependency resolution (i.e. HttpConfiguration.DependencyResolver) is optional and is now configured separately from the default services used by ASP.NET Web API (HttpConfiguration.Services). However, the service locator consults the dependency resolver first for required services and then falls back to explicitly configured services.
  • Improved link generation: The ASP.NET Web API UrlHelper how has convenience methods for generating links based on the configured routes and the request URI.
  • Register resource for disposal at the end of the request life-time: Use the RegisterForDisposeextension method on the request to register an IDisposable instance that should be disposed when the request is disposed.
  • Monitoring and diagnostics: You can enable tracing by providing an ITraceWriterimplementation and configuring it as a service using the dependency resolver. The ILoggerinterface has been removed.
  • Create custom help and test pages: You now can easily build custom help and test pages for your web APIs by using the new IApiExplorer service to get a complete runtime description of your web APIs.
  • Entity Framework based scaffolding for web APIs: Use the Add Controller dialog to quickly scaffold a web API controller based on an Entity Framework based model type.
  • Create unit test projects for Web API projects: You can now easily create a unit test project for a Web API project using the New ASP.NET MVC 4 Project dialog box.
  • Unauthorized requests handled by ASP.NET Web API return 401 Unauthroized: Unauthorized requests handled by ASP.NET Web API now return a standard 401 Unauthorized response instead of redirecting the user agent to a login form so that the response can be handled by an Ajax client.
  • Configuration logic for MVC applications moved under the App_Start directory: The configuration logic For MVC applications has been moved from Global.asax.cs to a set of static classes in the App_Start directory. Routes are registered in RouteConfig.cs. Global MVC filters are registered in FilterConfig.cs. Bundling and minification configuration now lives in BundleConfig.cs.
  • Add Controller to any project folder: You can now right click and select Add Controller from any folder in your MVC project. This gives you more flexibility to organize your controllers however you want, including keeping your MVC and Web API controllers in separate folders.

 

Author: "Ingo Rammer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Friday, 27 Apr 2012 13:02

Just found this and thought to share it with you: Network Class Library Team (System.Net): New Performance Counters for HttpWebRequest

 

Each of the seven green circles represents one of the six performance counters (there are two ‘5’ items because 5 is the average lifetime, and there are two code paths that will affect that counter).

 

Note: Be aware that ‘new’ means new in .NET 4.0 (the blog post is from Aug 2009).

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Thursday, 12 Apr 2012 08:24

The WCF team has set up a uservoice page for voting on WCF v-Next features. Go ahead and influence WCF!

Author: "Christian Weyer" Tags: ".NET, ADO.NET Data Services / Astoria, A..."
Send by mail Print  Save  Delicious 
Date: Monday, 02 Apr 2012 18:20

And here we go – as promised to all of you nice people attending one of my sessions last week in London.

 

If you have questions, please feel free to send my an email!

See you next year at DevWeek.

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Date: Tuesday, 06 Mar 2012 20:22

As much as I like WCF (and as much as I made money with it in the past years) – I think it is now time to re-think some approaches and some architectural ideas. What is ahead of a lot of us is what I call ‘light-weight architectures for reach’.

Just to give you some scope: I am one of the original Digerati board members of Indigo (WCF). Some people say I know WCF inside-out - I have given several dozens of introductions to WCF in seminars, conference and user group sessions world-wide and did numberless consulting gigs in Europe with WCF (and no, I did not really find time to write a book – besides a chapter here).

OK, so here goes...

There is currently a shift - or rather a new focus - in distributed application architecture. And no, I am not going to call it REST and I am not saying it is the one and only true thing from now on. But we have new drivers like application mash-ups, mobile devices and cloud computing which force us to move away from the good old feature-rich (and somehow heavy-weight) SOAP-based approaches. This development and this need is non-discussable and undeniable. One possible solution to these new needs is the use of light-weight Web APIs (which can be evolved into a REST-ful API or be used 'just' in an RPC-ish way).

So, which technology framework should we as .NET developers choose to build Web APIs? One choice is to leverage WCF's WebHttp model. After working with it for some years I quickly noticed a number of shortcomings (testability/mockability, serializers, ...) and wished that Redmond would come up with something better. *Of course* it had to be WCF, it had to be part of the overall "let's abstract away communication 'details'". And so it happened that they announced WCF Web API (and I was lucky enough to be part of the advisory board, again). All was fine in my world. It seemed.

Fine until I again realized that it has shortcomings when building some more flexible and advanced Web APIs. But this time it was actually the fact that the limitations were in WCF itself. The 'SAOP message' model of WCF just does not fit at all into this world. Everything the team tried to accomplish and to provide features for a web-based paradigm was just trying to put the round into the rectangle (and vice versa). For a web-based base framework maybe WCF is not the right choice.
And it turned out that there is a very good framework that can deal with the web and HTTP in a fantastic way. So, the decision to build a .NET web API framework on ASP.NET (and ASP.NET MVC, to be more precise) was somehow natural.
I personally had one very strong wish - something I have learned in the past years is invaluable for a lot of our customers... self-hosting! So, the advisors pushed hard to get self-hosting, and here it is: we can perfectly build our own host processes and host the exact same Web API implementation either there or in IIS/ASP.NET.

Today, I am quite happy with what happened. The only issue I still have is the name: I would definitely have not called it ASP.NET Web API, but rather .NET Web API. If you are working in my geographical area then you may understand why.

Anyway... talking a bit about application architecture (.NET server-side):
I would build a WCF service and an ASP.NET Web API (at least with the RPC-ish approach) as a facade only - the actual logic (business logic or data/resource access) is hidden beyond that facade. With this simple pattern it is no problem to have both WCF SOAP services and ASP.NET Web APIs sitting right next to each other happily ever after. I am doing it all the time. And you are then actually in the power to leverage the full power of each framework - get the most out of SOAP/XSD/WSDL/WS-* and the best out of web APIs/REST/whatever.

Fact is, I am using Web APIs quite a lot these days as we are building cloud-based systems in an increasing number and also cross-device mobile apps.

My 2 services cents.
Flame away.

Author: "Christian Weyer" Tags: ".NET, Architecture, ASP.NET, Azure, Dist..."
Send by mail Print  Save  Delicious 
Next page
» You can also retrieve older items : Read
» © All content and copyrights belong to their respective authors.«
» © FeedShow - Online RSS Feeds Reader