Minggu, 23 Januari 2011

RIA Services and Validation


BookClub Application ScreenshotEarlier today, my SilverlightTV recording on RIA Services and Validation went online. I used validation as a feature area to focus on this first recording on RIA Services, because I think it illustrates both the RIA Services value proposition and key elements of the vision around the project in a very direct manner. Specifically:




  • Focus on end-to-end solutions for data scenarios. It is not sufficient to just address querying data or submitting some changes, but about providing the infrastructure for managing data, editing with validation, tracking errors raised on client and/or server, rolling back changes, and more.

  • The server project and client project are logical halves of the same application. It would be great to preserve and propagate developer intent, and semantics from the database to the middle tier to the client, and share code across tiers where possible. In other words leverage intent and rules as close to the end-user, while enforcing them at each tier. Automatically.

  • Provide out-of-box solutions to common scenarios. The Entity class on the client provides a pretty complete implementation of working with data on the client. It provides identity management, change tracking, change notification, transacted editing and rollback capabilities, as well as tracking and surfacing validation and concurrency conflict errors. In particular, in the context of this post, Entity provides an implementation of infrastructure interfaces such as INotifyDataErrorInfo introduced in Silverlight 4, so you don't have to roll your own.



In my demo for SilverlightTV, I used a product catalog and product editing scenario (my favorite scenario if you ask folks on the team). However for MIX10, I used a Book Club scenario, which I think is quite a bit more interesting (with the potential to become my new favorite scenario).


Check out the video. And then come back to read further. My MIX10 summary post lists everything else going on in the Book Club sample (along with a link to all of the sample code), but the rest of the post focuses on the validation aspects.


Update 3/26/10: For those looking for a copy of the app demo'd on the SilverlightTV show, you can download the Store sample.



[Full post continued here...]

Silverlight 4 + RIA Services - Ready for Business: Authentication and Personalization


To continue our series, In real business applications our data is often very valuable and as such we need to know who is accessing what data and control certain data access to only users with privilege. Luckily this is very easy to do with RIA Services. For example, say we want to let only authenticated users access our data in this example. That is as easy to accomplish as adding an attribute, see line 2 below.

  1:     [EnableClientAccess]
  2:     [RequiresAuthentication]
  3:     public class DishViewDomainService : LinqToEntitiesDomainService<DishViewEntities>
  4:     {
  5: 




When we run the application, we now get an error. Clearly you can do a bit better from a user experience angle… but the message is clear enough.



image_thumb[93]





Notice there is a login option, so we can log in…



image_thumb[107]





and even create a new user.



image_thumb[108]





and with a refresh we now get our data



image_thumb[97]



And the application knows who i am on the client and gives me a way to log out.



Now you can also easily interact with the current user on the server. So for example, only return records that they have edited, or, in this case, log every access:





  1:         public IQueryable<Restaurant> GetRestaurants()
  2:         {
  3:             File.AppendAllLines(@"C:\Users\brada\Desktop\log.txt", new string[] {
  4:                 String.Format("{0}:{1}", DateTime.Now,
  5:                 this.ServiceContext.User.Identity.Name)});
  6:             return this.ObjectContext.Restaurants
  7:                 .Where (r=>r.Region != "NC")
  8:                 .OrderBy(r=>r.ID);
  9:         }
 10: 




Line 5 is the key one.. we are accessing the current users on the server. This gives us a nice simple log.



3/7/2010 9:42:57 PM:darb

3/7/2010 9:43:05 PM:darb



Now we can also personalize this a bit. Say we want our users to be able to give us a favorite color and we keep track of that on the server and the client, so it works seamlessly from any machine.



First we need to add BackgroundColor to our backing store. I this case I am using ASP.NET profile storage, so I add the right stuff to web.config



image_thumb[103]



Then I need to access this from the Silverlight client, so I add a property to the User instance in the Models\User.cs



    public partial class User : UserBase
    {
        public string FriendlyName { get; set; }
        public string BackgroundColor { get; set; }
    }


Finally, we need to access it on the client. In main.xaml add lines 2 and 3..



  1:   <Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}"
  2:         Background="{Binding Path=User.BackgroundColor}"
  3:         DataContext="{StaticResource WebContext}">
  4:
  5: 




Run it and we get our great default background color!



image_thumb[104]



Now, that is nice, but it would be even better to give the user a chance to actually edit their settings. So in About.xaml, we use a very similar model as above.



  <Grid x:Name="LayoutRoot"
        DataContext="{StaticResource WebContext}">


and



<sdk:Label Content="Background Color:" />
<TextBox Text="{Binding Path=User.BackgroundColor, Mode=TwoWay}" Height="23" />


Then wire up a save button



        private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            WebContext.Current.Authentication.SaveUser(false);
        }




And it works!



image_thumb[105]



And what’s better is if you run it from another browser, on another machine, once you log in you get the exact same preferences!



image_thumb[106]

Silverlight 4 + RIA Services - Ready for Business: Exposing WCF (SOAP\WSDL) Services


Continuing in our series, I wanted to touch on how a RIA Services can be exposed as a Soap\WSDL service. This is very useful if you want to enable the exact same business logic\data access logic is available to clients other than Silverlight. For example to a WinForms application or WPF or even a console application. SOAP is a particularly good model for interop with the Java\JEE world as well.



First you need to add a reference to Microsoft.ServiceModel.DomainSerivves.Hosting.EndPoints assembly from the RIA Services toolkit.



image



Then you need to edit the endpoints section of the domainserivces config in web.config file. Below I am showing the SOAP and OData endpoints enabled.


  <system.serviceModel>
    <domainServices>
      <endpoints>
        <add name='OData'
             type='System.ServiceModel.DomainServices.Hosting.ODataEndpointFactory, System.ServiceModel.DomainServices.Hosting.OData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' />
        <add name='Soap'
             type='Microsoft.ServiceModel.DomainServices.Hosting.SoapXmlEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' />
      </endpoints>
    </domainServices>
 
 
 


Now, all you have to do is navigate in the browser to this URL:


http://localhost:21516/BusinessApplication1-web-DishViewDomainService.svc


Note the pattern is [namespace]-[typename].svc


image


And we get the very familiar WCF service debug page.


And if you really want to drill in, here is the full WSDL describing the service.


image



You are done on the server, now let’s look at how you consume that on the client. For the sake of simplicity, I have created a new Console application. Right click on the project and select Add Services Reference.


image


image

  1: var context = new DishViewDomainServiceSoapClient();
  2: var results = context.GetRestaurants();
  3: foreach (var r in results.RootResults)
  4: {
  5:    Console.WriteLine(r.Name);
  6: }
  7: 


The code for query is very simple. Line 1 creates the client proxy, line 2 does a synchronous call to the server. Then we simply loop through the results.



image



Updating the data is a little bit more interesting… I need to create a ChanageSet that I populate with any updates. in this case I am updating just one value. I also need to send the original value back to the server.

  1: var changeSet = new ChangeSetEntry();
  2: var org = new Restaurant();
  3: org.ID = entity.ID;
  4: org.Name = entity.Name;
  5: entity.Name = 'Updated:' + entity.Name;
  6: changeSet.Entity = entity;
  7: changeSet.OriginalEntity = org;
  8: changeSet.Operation = DomainOperation.Update;
  9: var updateResults = context.SubmitChanges(new ChangeSetEntry[] { changeSet });
 10: 



And you can see the result of running this a couple of times:


image



For more information, see Deepesh’s post on Configuring your DomainService for a Windows Phone 7 application



For V1.0, this post describes the RIA Services story for WPF applications. While it works, it is clearly not the complete, end-to-end solution RIA Services offers for Silverlight. For example, you may want the full experience: the DataContext, entities with validation, LINQ queries, change tracking, etc. This level of support for WPF is on the roadmap, but will not make V1. But if you like the RIA Services approach, you might consider DevForce from IdeaBlade or CSLA.NET which works for both WPF and Silverlight. The great folks at IdeaBlade have offered me 10 free licenses to give out. If you are interested in one, please let me know.

Enterprise Library 5.0 and Unity 2.0 BETA1 released

Enterprise Library 5.0 and Unity 2.0 BETA1 released: "Microsoft patterns & practices team is pleased to announce the release of the Enterprise Library 5.0 Beta1 and Unity 2.0 Beta1 - February 2010."

Silverlight 4 + RIA Services - Ready for Business: Ajax Endpoint


Continuing in our series, I wanted to touch on how a RIA Services can be exposed your service in JSON. This is very handy for Ajax clients.

The great thing is that enabling the JSON endpoint is that it requires NO changes whatsoever to the DomainService. All you need to do is enable it is to add the JSON endpoint in web.config

  1:   <system.serviceModel>
  2:     <domainServices>
  3:       <endpoints>
  4:         <add name="JSON"
  5:              type="Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  6:         <add name="OData"
  7:              type="System.ServiceModel.DomainServices.Hosting.ODataEndpointFactory, System.ServiceModel.DomainServices.Hosting.OData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  8:         <add name="Soap"
  9:              type="Microsoft.ServiceModel.DomainServices.Hosting.SoapXmlEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
 10:       </endpoints>
 11:     </domainServices>
 12: 




As you can see, this above snippet shows adding the JSON endpoint from the RIA Services toolkit as well as the OData and Soap ones.



You can see the endpoint results navigate to the URL in this format:



http://localhost:21516/BusinessApplication1-web-DishViewDomainService.svc/Json/GetRestaurants



image





{"GetRestaurantsResult":{"TotalCount":-2,"IncludedResults":[],
"RootResults":[{"Address":"49 Gilbert St.","City":"London",
"ContactName":"Charlotte Cooper","ContactTitle":"Purchasing Manager",
"Fax":"(171) 555-2222","HomePage":"","ID":1,"ImagePath":
"Restaurant_Alinea.jpg","Name":"Alinea - Updated from Ajax",
"Phone":"(171) 555-2222","PostalCode":"EC1 4SD","Region":""},
{"Address":"P.O. Box 78934","City":"New Orleans","ContactName":
"Shelley Burke",
"ContactTitle":"Order 




As you can see – some nice looking JSon. Now, to write a very simple Ajax client.



Below is an example query method in the Ajax client



         function query() {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open("GET", "BusinessApplication1-web-DishViewDomainService.svc/Json/GetRestaurants", false);
            xmlhttp.send();
            var rawResults = JSON.parse(xmlhttp.responseText);
            var results = rawResults.GetRestaurantsResult.RootResults;
            var entity
            for (var i = 0; i < results.length; i++)
            {
                entity = results[i];
                document.getElementById('results').innerHTML += ' <br> ' + entity.Name;
            }
          
        }


This is wired up to to a very simple button



        <button type="button" onclick="query()">
            Query</button>

image



Update is just a bit more tricky… but still basic:



        function update() {
            var operation = {};
            operation.Entity = { "__type": "Restaurant:#BusinessApplication1.Web", "ID": 1, "Name": "Alinea - Updated from Ajax"};
            operation.OriginalEntity = { "__type": "Restaurant:#BusinessApplication1.Web", "ID": 1, "Name": "Alinea" };
            operation.Operation = 3; //update
            var csData = JSON.stringify({ "changeSet": [operation] });
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open('POST', 'BusinessApplication1-web-DishViewDomainService.svc/Json/SubmitChanges', false);
            xmlhttp.setRequestHeader("Content-Type", "application/json");
            xmlhttp.send(csData);
            var results = xmlhttp.responseText;
            document.getElementById('results').innerHTML = results;
        }






In this demo, we showed how to enable the Ajax\JSON client for RIA Services.

My Last Day at Microsoft


Wow – I can’t believe it has already been 13 years at Microsoft. I have had a great time here and learned so much from the smart and passionate people I work with as well as the incredible developer community around .NET. But I have decided it is time for me to try something new – so my last day at Microsoft will be Friday, April 23rd .

While I am leaving Microsoft, I continue to have a positive view of the company. No other company has the footprint that Microsoft does on the industry. I am confident that the company will continue to have an impact in the years to come. I will be looking forward to watching the next release of .NET from outside.

Of course, there is never a good time to leave, but I feel a great sense of accomplishment shipping Silverlight 4 and Visual Studio 2010/.NET Framework 4. The technologies I have been most closely involved with have found amazingly good homes. MEF and RIA Services are in the right teams and on the right track long term and I believe those technologies will have great futures.

What I loved most about my time at Microsoft is the opportunity to work with some of the smartest, most passionate people in the industry to ship some great software that customers LOVE. As I have been thinking about this transition, I have reflected on a few of the releases I have been a part of and what I learned in the process. Hopefully you can take these learnings as my last words of wisdom to you.

  • MS-Travel (later spun off as Expedia ) - My first experience at Microsoft as an intern in Test. I landed the job because I was able to help my future boss debug a VB issue in the interview ;-). I learned what it was to be a PM and I fell in LOVE with it.
  • VB 5 - I came back the next summer as a PM intern and found my sweet spot – PM in the developer space. I was a PM on the Control Creation Edition of VB 5 and learned the blocking and tackling of consensus building, prioritization and specing!
  • IE4 and IE4.01 with Win98 - It was so energizing to be involved in the first browser wars. At the time, I think we had IE4, 5 and 6 all going in parallel! As Release PM I learned a ton about shipping: balancing priorities, triaging, war rooms, and working very broadly across teams.
  • Common Language Runtime (“Lightning”) and overall .NET Framework (“Project 42”). In the 4+ years incubating the first release I got my taste for “doing a V1” and I loved it! We all *knew* we were changing the industry with our work as much as we knew the project could be canceled at any time. After PDC2000, when we came out of the veil of secrecy, I learned about how to listen to customers and got hooked on bringing customer feedback into the product with the DOTNET@DISCUSS.DEVELOP.COM email list. If you were on that email list at the time, you helped shape what become the glasnost of Microsoft that lead to weblogs.asp.net, blogs.msdn.com, and eventually channel 9 and the whole community arm of MS.
  • .NET Framework 1.1 (“Everett” ) and .NET Framework 2.0 (“Whidbey”) - Between these two releases, I learned about the “V2 trap”. That is, the critical importance of having a clear vision for a release rather than just “make stuff better”. It is so much more valuable to customers, and therefore more satisfying for engineers, to work on “3-big bets” rather than peanut-buttering our efforts over a bunch of small “rounding out” features.
  • .NET Framework 3.0 with Windows Vista (“WinFX”) – Back to my “V1.0 passions”, with this release we aimed to make .NET the most important programming model for Windows. With broad new technologies, WF, WinFS, WCF and WPF there was a LOT of new stuff. I was asked to bringing this work together to a coherent whole. I learned a TON about how to develop software at scale and what works (and doesn’t) across such a large organization. This experience also gave me much deeper insight into executive decision making and what works (and doesn’t) to get the most effective decisions made.
  • ASP.NET 3.5, ASP.NET AJAX and ASP.NET MVC – I learned a whole new development area – AJAX and the web. This time lit my passion for the web development area that I continue to believe is a game changer. I learned the value of shipping out of band releases to clearly address customer scenarios as they emerge. I also learned the value of small, lightweight (download size, concept count, etc) frameworks.
  • Silverlight 2, 3 and now 4 That rate of maturation of Silverlight has been amazing. From the first release where there was literally no button, to Silverlight 4 where we have a viable line of business platform. Here I learned a lot about how to do small, frequent, incremental releases.
  • MEF – This technology has a huge potential to change the core patterns the average .NET Developer uses to build their applications. Through this release, I learned two big things: The value of a close customer (eg VS) shaping and guiding requirements and how to work diligently with the community in a very transparent way (shipping source, open license, etc).
  • WCF RIA Services - The thing I love about RIA Services is that we tackled an end-to-end customer scenario that crossed database, mid-tier, client and tooling to deliver really compelling customer value. While this sort of end-to-end thinking forced us to work very closely with many teams, the results were fantastic! Out of this release I learned the value of focusing on the end-to-end rather than just one small island.

I am deeply grateful for the opportunities I have had at Microsoft in working with such an amazing set of co-workers and vibrant community.

Initially, I am going to take some time off to enjoy the wonderful spring weather in Seattle and visit Legoland with the kids before starting my next endeavor.

While I will not be as deeply involved in the .NET Developer Community – I will be keeping up and enjoying the successes I know you will have. Good luck and have a great time!

I’d love to stay in touch:

Email: BradA42@gmail.com

Blog: http://bradabrams.com

Twitter: @BradA

Facebook: Brad Abrams

Upcoming Script# Release and LIDNUG presentation

Upcoming Script# Release and LIDNUG presentation: "A quick heads up on a Script# presentation for the Linked.NET user group on LinkedIn, and some words (ummm... teasers) on the upcoming script# release...
[Full post continued here...]"