WCF Tutorial: now on YouTube

Advertisements

.Net:a client for an IIS-hosted WCF service

This is the third and last post on the basics of WCF usage. I use SoapUI to consume the WSDL which exposes the single method we created in the first post, and hosted using IIS in the second post. None of this covers how to install SoapUI, although hopefully there is enough here to show you how to use it.


 

At the end of the previous post, we had access to the service wsdl via the link in blue:

WCFinIIS15

Click on the link, and from the URL that comes up next, copy that to the clipboard:

WCFinIIS16.JPG

Start SoapUI, and create a project as shown here. My PC is called [i7], so adjust your entries to match your setup, and then click OK:

WCFinIIS17

After that, the left side panel should look something like this:

WCFinIIS18

Double click [Request 1] and the main panel looks like this:

WCFinIIS19

Just to see what happens, click the green play button in the TLH corner:

WCFinIIS20

If you now put e.g. 101 rather than the default [?], you get…

WCFinIIS21

, which is exactly what we expect and want.

 

.Net: simplest WCF service and client

In VS2015, I wanted to create the very simplest possible WCF service, and a client, in the form of a console app, to prove it works.

In VS, use the WCF template to create a WCF service library. As the template is a Hello World, I choose to call it HelloAcmeService (I don’t know why I’m randomly picking fictitious brands):

That creates an interface file, and a class file, which contain more than I want, so we strip those back to a minimum, and do some renaming.

Before:

HelloAcmeService02


HelloAcmeService03


HelloAcmeService04


HelloAcmeService05


 

After…

…removing the stuff I don’t want, and some renaming:

HelloAcmeService06


 

HelloAcmeService07


HelloAcmeService08


HelloAcmeService10

After an OK build let’s make sure we can reference it from the browser, by pressing Start in VS , and then clicking on the BaseAddress hyperlink  in the app.config (or just typing it in):

HelloAcmeService11

Now we could plug the WSDL into SoapUI and get a richer client experience (if those words mean nothing, that can be for another tutorial). For now, we’ll just create a console app to use the service.

Stop the service running in VS, so you can go back to editing. Create a console app under the solution (please note – there is in fact a compile error later using this name for reasons I am not going into here, and I won’t redo the screenshots – please call the console app HelloServiceAClient – note the ‘A’):

HelloAcmeService12

That gives you this new content in the Solution Explorer:

HelloAcmeService13

You now need to add a Service Reference to use the service from this client. Right click on References/Add Service Reference…, and in the dialogue, click Discover:

HelloAcmeService14

Click OK, and Solution Explorer now looks like this:

HelloAcmeService15

Now in Program.cs, add the text highlighted to access the service and use the GetData() method from the service:

HelloAcmeService16

The last action before testing it is to right-click on HelloServiceAClient and select Set as Startup Project.

HelloAcmeService17

Now press the Play button in VS, and you get this exciting output:

HelloAcmeService19

That’s it.

 


RIA WCF services: Domain Services and query cost on the database

From the Northwind database, I’ve generated an entity model consisting of the Orders table. For the domain service, right now, I just have an unconstrained table scan, which of course you would never do in practice. This is generated code:

DomainService01

DomainService02

If we pass in this query from the Domain Context:

DomainService06

, then this is what we see in SQLProfiler, as expected (well, all of it’s as expected):

DomainService05

That is, there is no restriction or sorting on the query.

What if we add a sort to the query, for example:

DomainService04

This is what we get in Profiler, again, as expected, in that our OrderBy has been executed on the database server:

DomainService03

However, what you cannot tell from Profiler is the query plan.

(actually, that’s not true: digging around SQL profiler for the plan is just not much fun if you have the realtime facts to hand as an alternative)

.For that, copy and paste the text into SSMS:

DomainService07

It has to plough through the whole of the table anyway, but it is made more inefficient by the fact that ShipCity is not an indexed column. Let’s compare that plan with one where the Order By is on an indexed column – we’ll use OrderId, which is the PK column:

DomainService08

The big difference is that when you sort by ShipCity, SQL has to add in a sort operation, whereas when you sort by OrderId, because the key is clustered around that column already, then it is already in the right order.

Comparing the relative performance and cost of the 2 queries (if you didn’t know, just run both queries in the same SSMS windows):

DomainService09

As we already knew, the sort operation more than doubles the cost.

If you want to follow the database example, see my links here about Northwind.

WCF RIA services – Convention based CRUD operations

1 of obviously a number of posts on MSDN on Domain Services:

msdn01

I was going through this Pluralsight course on RIA services, entering the examples in by hand. In 1 example, there was a domain service class with a query method, and an update method. I wanted to be clear on 1 thing at a time, so I just did the query method to start with. This was against a Singleton implementation of a set, for what that’s worth.

So the query went fine (other than the issues re path length, for which I’ve yet to categorically prove the cause). I then moved to a section where 2 datagrids were each instantiating their own copy of the domain context. The idea was that you changed a value in one DataGrid, ran SubmitChanges(), and then refreshed the other grid, getting the just-saved change back from the server, such that the change was reflected in both grids.

Now, accepting that I had only implemented the Query part of the Crud set, I just noted that I got this error when moving from 1 row to another following a change (but before  sending SubmitChanges()):

UpdateError01

 

But given I hadn’t implemented the update, that kind of didn’t surprise me. But when I looked at the Domain Service code for the update, I could not see how it related to the SubmitChanges() action:

    public void UpdateComposer(Composer composer) {
	data.Update(composer);
    }

… particularly when the data model method looks like this:

public void Update(Composer composer) {
			var current = _composerList.Find(p => p.ComposerId == composer.ComposerId);

			if (current == null) {
				throw new KeyNotFoundException("No Composer found with that key");
			}

			current.Fname = composer.Fname;
			current.Lname = composer.Lname;
			current.BirthDate = composer.BirthDate;
			current.AgeAtDeath = composer.AgeAtDeath;
		}

So I then implemented the above 2 Update methods. You only need to know that it worked, but I was puzzled that it had found its way to the apparently arbitrarily named UpdateComposer method. I then changed the name of that Domain Service method to UpdateXComposer. It still worked. I then changed it UpdatXeComposer.

This time it allowed me to move from 1 row to the next in the grid, but when I tried to SubmitChanges, I got this message:

UpdateError02

So this means that RIA services, is just looking for any old method that starts with Update. In fact trying a nonsense name, it still hits the breakpoint:

UpdateError03

What happens if I then duplicate the method, but given one a different name? Compile-time error:

UpdateError04

So they at least tested it. 🙂

And on an unrelated point, this is the compile error you get if you forget to decorate your key field in your data class with a [key] attribute, ie if you fail to do this:

public class Composer {
    [Key]
     public int ComposerId { get; set; }

UpdateError05

Coming back to the use of a nonsense string in the method name, let’s focus on the name, or part name, as seems to be significant, of the method, prove (again) that it works as-is, and then look for the string in a decent text editor from the root of the solution down.

Here is the Domain Service method, again, this time with the surely unique on my PC string in the name [stuffx]:

stuffx01

Prove it works:

stuffx02

Yes. I edited Haydn to become Haydnx, and it was saved back to the server.

Now we look for the string from the solution root down:

stuffx03

 

In 1 non-compiled location only. So clearly some convention-based, inference-based compilation going on. Fine.

 

Silverlight and WCF

Spent a few hours today with Laurent Bugnion’s Silverlight book, and trying to get one of his Silverlight/RIA Services examples to run. (It is a beautiful book – the use of colour in the code makes an impact.) In fact out of the box, I don’t see how it could run, as the web service contract name referenced in the client is not the same as that generated from the service. Unleashed01 But even after that, I still couldn’t get it working, defined as the catch-all error [The remote server returned an error: NotFound] There are various references to this as being a super-unhelpful message.

So I have 2 solutions running concurrently, one the service project, one the client project. In the end, in the service project, I created a Silverlight-enabled Web Service, and copied the code in the “traditional” web service sideways. I then browsed in the server to the URI, went to Service References in the Client project, created a new reference, deleted the existing one(s), rebuilt… and it worked: Unleashed02 So I don’t see how that would have worked out of the box either… but he’s obviously very good so maybe I’m wrong. Working out a WCF issue is always good for the soul. I also installed Fiddler for the first time on a home PC – what a load of rubbish we let through our home machines! Quite interesting was remembering that when you generate a service in Visual Studio, the WCF test client is pretty useful for passing calls. It even returns complex data, assuming you have some test data. Unleashed03 In fact there is little difference between the 2 service implementations other than name, so maybe it was somehow finger trouble, dunno. Unleashed04 ClientAccessPolicy – for what that’s worth… Unleashed05 Unleashed06

This msdn link is quite good on Silverlight and data access:

Unleashed07

 

And although I didn’t need it in the end, xsd.exe from the Windows 8.1 SDK is pretty useful – it can take XML as input, and infer an XSD from that. Then from that, you can build classes.

Credit to this person.

xsd01
xsd02
xsd03
xsd04

d