11

I have a project that needs to implement WCF data services (OData) to retrieve data from a control system (.NET Framework Application). The WCF data service needs to be hosted by the .NET application (No ASP.NET and NO IIS).

I have seen many WCF Data Service examples recently; they are all hosted by ASP.NET application. I also see the self-host (console application) examples, but it is for WCF Service (not WCF Data Service).

It is possible to have a standalone .NET Applications to host WCF Data Services (http: //localhost:1234/mydataservice.svc/...).

If yes, can someone provide an example?

Cœur
  • 37,241
  • 25
  • 195
  • 267
warmcold
  • 119
  • 1
  • 3
  • Have you tried? Have you been able to self-host a normal WCF service? – John Saunders Jun 15 '10 at 05:09
  • 1
    Bounty will go to marc_s after the time limit is up. (For his fantastic answer that saved me tons of time.) No new answer is needed for the bounty. – Vaccano Jul 22 '11 at 16:42

1 Answers1

28

I just tried the same thing - and yes, you can host a WCF Data Service in your own assembly - with a few little tricks.

Here's how:

  • put your data model (EF Data Model) into its own assembly, let's call it DataModel

  • create a new class library project (call it MyDataServiceHost)

  • add a few references:

    • your DataModel assembly with the data layer
    • System.ServiceModel
    • System.ServiceModel.Web
    • System.Data.Services.Client
    • System.Data.Services - you cannot pick this from the usual Add Reference dialog under the .NET category - you need to browse for the assembly file. Find the directory C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0 (or C:\Program Files (x86)\... on a 64-bit machine) and pick the System.Data.Services.dll inside it
  • add a new class to that class library and call it e.g. YourDataService.cs - it will look something like this:

    using System.Data.Services;
    using System.Data.Services.Common;
    
    using DataModel;
    
    namespace MyDataServiceHost
    {
        public class YourDataService : DataService<YourModelEntities>
        {
            // This method is called only once to initialize service-wide policies.
            public static void InitializeService(DataServiceConfiguration config)
            {
                // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
                // Examples:
                config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
            }
        }
    }
    

    You can name the class anything you like, and it has to derive from DataService<T> where T is the name of your data model; if you're using Entity Framework, it's the name of your object context class - typically something like (database)Entities or whatever you picked when you created the EDM

  • add another class to your new project, call it MyDataServiceHost.cs and it will look something like this:

    using System;
    using System.Data.Services;
    
    using DataModel;
    
    namespace MyDataServiceHost
    {
        public class MyDataServiceHost
        {
            public static void LaunchDataService(string baseAddress)
            {
                Uri[] baseAddresses = new Uri[1];
                baseAddresses[0] = new Uri(baseAddress);
    
                using(DataServiceHost host = new DataServiceHost(typeof(YourDataService), baseAddresses))
                {
                    host.Open();
                    Console.WriteLine("DataService up and running.....");
    
                    Console.ReadLine();
                    host.Close();
                }
            }
        }
    }
    

    It instantiates a DataServiceHost, which is derived from WebServiceHost (which in turn is derived from ServiceHost) and it will spin up the WCF Data Service runtime for you.

  • now you can start up your WCF Data Service from any app using:

    MyDataServiceHost.LaunchDataService("http://localhost:4444/YourService");
    
  • last thing to remember: the app that you use to launch the WCF Data Service must have the connection string (the EDM connection string, if you're using Entity Framework) in its app.config (or web.config) in order for this to work!

thirtydot
  • 224,678
  • 48
  • 389
  • 349
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • If you are watching this question anymore, I followed your answer and got the service running, but when I try to view it in firefox like this: http://localhost:4444/EntitySearch/Countries I get this result: `Resource not found for the segment 'Countries'.` I double checked my EF code and that class is there ('public ObjectSet Countries') Any ideas? – Vaccano Jul 22 '11 at 17:13
  • I had misspelled the 'InitializeService' method name. (Grr, should have just copied and pasted.) – Vaccano Jul 22 '11 at 18:11
  • I would recommend installing the WCF Data Services Server NuGet package instead of navigating to a local assembly for the reference to System.Data.Services. – Kilhoffer Dec 07 '13 at 23:31
  • I have 3 projects in VS2012: _WCF Service Host, ASP.NET WEB API, and WCF DataService_. **Output Path is the same** MyServices\bin\Debug folder for all 3. In development, useful Self Hosting each project. Anyways, **Web.config is common** for all 3. Now, is it possible ***hosting all 3 projects in the same IIS WebSite*** ? ***Conclusion***: _In development, Self Hosting (WCF, WCFDataService, WebAPI). In stagging, Hosting all in the same website._ – Kiquenet Oct 22 '14 at 18:00