|
Friday, October 30, 2009 State of .NET and User Group Presentations in Denver I just got back from doing a State of .NET Event in Denver as well as a user group presentation there. It was fun. Thanks for the warm welcome “Denverers” (what do you call people from Denver?). For those of you who attended one of the presentations, don't forget to sign up for a CODE Magazine subscription using one of the special URLs provided. For those of you who weren't there, you can still get a great CODE Magazine offer here. Also, don't forget to subscribe to the free CodeCast podcast. Here is the slide deck for these talks:
Also, I promised additional examples to download, so here they are:
Also, for more information on Silverlight and related Expression products, see www.Silverlight.net/GetStarted
For more information on our Tower48 escrow company, check out this post, or go to www.Tower48.com. Also, here is a video on the Tower48 stuff:
And here is a video of the Silverlight hockey app:
The external download link for the video is this: http://www.youtube.com/watch?v=BD8OPqtHYdg
Posted @ 4:24 PM by Egger, Markus (markus@code-magazine.com)
Tuesday, October 06, 2009 Cross-Site Access Policy for Self-Hosted WCF Services When you build WCF Services you basically have to options in making the
service available: 1) host in IIS, and 2) self-host in something like a Windows
Service or similar application. In general, it is easier to let IIS host the
service, because it offers features such as service-health-monitoring. Plus, it
is easier to just put a service into an ASP.NET based application as a .svc
endpoint. I use this ability myself, for both HTTP and TCP/IP based
services.
However, there are also scenarios where I prefer the self-hosting route. This
is especially true for my more important and more powerful services, because
those are typically the services I expose in a number of different formats and
over a number of different protocols. In self-hosted scenarios, you generally
have more options to expose the same service. For instance, I may want to expose
a service over TCP/IP, HTTP (SOAP and REST), and MSMQ all at the same time. And
yes, they are not all the same exact services (queued ones for instance, aren’t
going to return a result, while SOAP services do, as do REST services, but they
are still separate classes). Even so, they often are wrappers around the same
business logic and generally go together. So self-hosting may be of interest
there.
Using WCF, exposing services (SOAP and REST) using the HTTP(s) protocol in a
self-hosted scenario is not very difficult. You simply create a host app, add
the appropriate WCF ABCs (well, Address and Binding, mainly… the Contract will
be the same exact thing regardless of how you host the service), and you are
pretty much ready to go. (There actually is a bit of a gotcha when you compete
with IIS for a URL, but I will blog about that separately).
The one thing that people often ask me when it comes to this stuff is “how do
I call this from Silverlight”. Silverlight by default does not allow
cross-domain calls. This means that a Silverlight component that is part of http://codemag.com cannot automatically access a
service on http://www.epsservices.net.
To do this, the domain that hosts the service (www.epsservices.net in this example) needs
to define a cross-site access policy. It explicitly needs to opt in to allow
services on that domain to be called from another domain.
Note that in these types of self-hosted scenarios you almost always have
a cross domain call. Even if you only have a single site that calls the service,
it is unlikely that the self-hosted service grabs the same domain as the actual
web site hosting the Silverlight component. It can be done, but just from an
architectural and maintenance point of view, it tends to get very
confusing.
Anyway: What you need is a ClientAccessPolicy.xml file in the
root of the domain that hosts the service. The
XML file content is fairly simple. Here is an example that allows for unlimited
cross-site access: <?xml version="1.0" encoding="utf-8"?> <access-policy> <cross-domain-access> <policy> <allow-from http-request-headers="*"> <domain uri="*"/> </allow-from> <grant-to> <resource path="/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access> </access-policy>
Note that this leaves the server wide open. In the wild, it is better to
limit callers to the exact set you actually need. Typically, that might mean
limiting access to SOAP headers from 2 or 3 caller domains, or something like
that.
On a side note, it is also possible to use a CrossDomain.xml file
instead. However, this is an Adobe format which Microsoft supports. This is not
a file specifically created for Silverlight and it doesn’t support the same
options and Microsoft won’t be able to add anything to that file format if
needed. You should only use a CrossDomain.xml file if you have a real reason and
understand the implications. Otherwise, stick with the ClientAccessPolicy.xml
file. Also, contrary to common misconception, it is not
necessary to have both files. Just a ClientAccessPolicy.xml file is all
you typically want/need.
Anyway: If your server is running IIS, you can simply put the
ClientAccessPolicy.xml file into the root folder of the domain. Silverlight will
then access the file to figure out what the server opts in for.
One scenario you may run into is that the WCF server does not run IIS at all.
After all, if you have a server dedicated to running these services in a
self-hosted fashion, then why even run IIS? Just to serve up one XML file? That
is probably overkill, especially considering that this opens the server up
security-wise, and you also might run into trouble with IIS competing for URLs
and such. Not to mention that every service running consumes resources. So if
all you need is serve up this XML file, then don’t run IIS. Instead. have your
WCF service host serve up the policy file as well. Here’s how:
First, create a service contract that can serve up XML content:
[ServiceContract] public
interface IClientAccessPolicy { [OperationContract] [WebGet(UriTemplate = "/clientaccesspolicy.xml")] XElement GetClientAccessPolicy(); }
There are some interesting aspects here. Fundamentally, this is a pretty
simple WCF contract that happens to return an XElement. The interesting part is
that this services – just like the REST service WCF can now host – supports
simple web-get access, which means it can be accessed as a plain URL. The URL
specified in this case is specified in the URI Template, and for this type of
operation it is always the same (ClientAccessPolicy.xml in the root folder). So
now, whenever someone goes to that file name in the root URL, this service can
kick in and return a result.
As you can imagine, the actual implementation of this service is trivial, as
all that’s needed is a single method that returns the desired XML as an
XElement. A good, simple, and flexible way to do this is using LINQ to XML for
this. But you can implement this any way you want. (In fact, you can probably
use other return types that represent XML).
So now, all that’s left to do in your host application is to fire up this
service using the WebHttpBehavior. Something like this will do fine:
Uri[] addresses = new Uri[] { "www.mydomain.com" }; var host
= new ServiceHost(typeof(ClientAccessPolicy),
addresses); var
endpoint = host.AddServiceEndpoint(typeof(IClientAccessPolicy),
new WebHttpBinding(), string.Empty); endpoint.Behaviors.Add(new WebHttpBehavior()); var
smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; host.Description.Behaviors.Add(smb);
There you have it! Now your self-hosted WCF service can host the client
access policy “file”. No IIS needed or even desired.
Posted @ 7:10 AM by Egger, Markus (markus@code-magazine.com)
Monday, October 05, 2009 Dynamically Loading Resource Dictionaries in Silverlight 3 At this fall’s BASTA conference in Mainz, I presented a session on “Reusable
Silverlight Components”. One of the things I showed in that session was how to
create Silverlight components that can be hosted in different sites and also be
completely re-styled and rebranded by means of dynamically loaded Resource
Dictionaries.
Silverlight v3 is the first version of Silverlight that supports resource
dictionaries. This makes it much easier to maintain resources generically in
separate XAML files, and even switch between different sets of resources. One of
the possibilities that often goes overlooked however, is that resource
dictionaries can be loaded completely dynamically from any URL. I often use this
in scenarios where I pass parameters to a Silverlight control, where one of the
parameters is the URL of such a resource dictionary. I then load that dictionary
dynamically, so everything in that application references that dictionary. The
basic idea is the dynamic load process from a URL. This can be done like so:
WebClient request =
new WebClient(); request.DownloadStringCompleted += new DownloadStringCompletedEventHandler(request_DownloadStringCompleted); request.DownloadStringAsync( new Uri("http://domain.com/mydictionary.xaml", UriKind.Absolute));
This triggers an asynchronous string download from the specified URL. The
associated event handler fires when the download is complete and assigns the
loaded resource dictionary:
void
request_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { string
resourceXaml = e.Result; ResourceDictionary
dictionary = Application.Current.Resources as ResourceDictionary;
dictionary.MergedDictionaries.Add( (ResourceDictionary)XamlReader.Load(resourceXaml)); }
This accesses the current application resources (which should be a resource
dictionary, although some error handling may be appropriate here) and then uses
a XamlReader to load the retrieved XAML string, casts it to a resource
dictionary (which it may not be, so more error handling is in order here) and
then simply adds it to the collection of available resource dictionaries.
There are a few more things of interest here that are worth pointing out:
First of all, Silverlight 3 still doesn’t support dynamic resources. Static
resources get assigned as soon as an interface loads and can’t be changed later.
This means that the new resource dictionaries should be added before any real UI
loading is done. I generally like to allow for a “resourcedictionaries”
parameter passed to the Silverlight control, but I make the parameter optional.
For this reason, I generally have this kind of code in my Startup event handler
in App.xaml.cs:
private void
Application_Startup(object sender, StartupEventArgs e) { if (e.InitParams.ContainsKey("resourcedictionary")) { var content = new Grid(); this.RootVisual = content;
content.Children.Add(new LoadingAnimation()); WebClient request = new WebClient(); request.DownloadStringCompleted
+= new DownloadStringCompletedEventHandler(request_DownloadStringCompleted);
request.DownloadStringAsync( new Uri(e.InitParams["resourcedictionary"], UriKind.Absolute)); } else {
var root = new Page1(); } }
This code checks for the parameter. If it isn’t present, the root UI
(Page1.xaml in this case) is loaded right away. Otherwise, I create a Grid() as
a root container (the RootVisual setting can only be assigned once, so I am
using the Grid object as a container which I can then use to load other UI into)
and I then load a temporary loading screen while resource dictionaries are
downloaded (you never know how long that might take). Then, when the dictionary
is downloaded, I merge it into the resources and then I load the real UI into
the Grid:
void
request_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { string resourceXaml = e.Result; ResourceDictionary dictionary = Application.Current.Resources as
ResourceDictionary;
dictionary.MergedDictionaries.Add( (ResourceDictionary)XamlReader.Load(resourceXaml));
var grid = this.VisualRoot as
Grid; grid.Children.Clear();
grid.Children.Add(new Page1()); }
Using this approach, the main UI (Page1) gets loaded after the custom
dictionaries are downloaded and thus all static resources pick up the new
styles.
Note: If you use the Implicit Style Manager, some of this is not as
critical, since the ISM manually applies styles whenever it is invoked. However,
since you are likely to still use named styles (which are always static), you
probably still have the same problem.
Another interesting thing to note here is that I am simply adding the new
dictionaries to the collection of merged dictionaries. The way Silverlight looks
up resources, the resources added last are found first. So if my application
already has a dictionary with a style called “StandardButtonStyle” and a
dictionary that is added later also has a style of the same name, the one loaded
last is found and used. This means that dynamically loaded resource dictionaries
can define a few new styles as needed. Since the standard resource dictionaries
remain in place, Silverlight will find all the default styles there, but the new
dictionaries can override only specific ones. If you completely replace all of
the application’s resources, then the newly loaded dictionaries would have to
define every single resource or else the control would show an error and
probably fail to load. So adding resource dictionaries in addition is generally
a nifty technique that works very well in the real world.
Posted @ 12:14 PM by Egger, Markus (markus@code-magazine.com)
Monday, October 05, 2009 BASTA Session Materials OK, this took a bit longer than expected, but here are my session materials
from the German BASTA Conference in Mainz. The download includes all 4 sessions
(C# 4.0 Dynamic, WPF & Silverlight Styles, Silverlight Reuse, and iPhone
Development for .NET Developers).
Click here to
download
Enjoy!
Posted @ 11:33 AM by Egger, Markus (markus@code-magazine.com)
|