简体   繁体   中英

Simple REST WCF Service Example Code - Endpoint not found

I was trying an example partially from Chapter 5 - RESTful .Net , but couldn't make it work for some reason (receiving 404-Not found).

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;

[ServiceContract]
public class RestService
{
    [OperationContract]
    [WebGet(UriTemplate = "Hosting")]
    public void Hosting()
    {
        Console.WriteLine("RestService::Hosting()");
        WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
    }

    static void Main(string[] args)
    {
        var host = new ServiceHost(typeof(RestService));
        var endpoint = host.AddServiceEndpoint(typeof(RestService), new WebHttpBinding(), "http://localhost:8080/Hosting");
        endpoint.Behaviors.Add(new WebHttpBehavior());

        host.Open();
        Console.ReadKey();
    }
}

It works (returns status-code OK) if I use WebServiceHost as follows

    static void Main(string[] args)
    {
        var host = new WebServiceHost(typeof(RestService), new Uri("http://localhost:8080"));
        host.Open();
        Console.ReadKey();
    }

So the question is how to make it work with ServiceHost (without any configuration file etc. if possible) ?

WebServiceHost creates an EndPoint for you, nothing wrong if you continue using it. Refer this link for more details...

But you can also add below configuration to your service configuration to use ServiceHost , I have given an example, you can change it to reflect your service classes.

<system.serviceModel>
        <services>
            <service name="YourService.DateTimeService" behaviorConfiguration="customBehavior">
                <endpoint address="Basic" binding="basicHttpBinding" contract="DifferentBindings.IDateTime">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>             
                <endpoint address="Web" binding="webHttpBinding" contract="DifferentBindings.IDateTime" behaviorConfiguration="webHttpBehavior">
                    <identity>
                        <dns value="localhost"/>
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />                
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8731/DifferentBindings/DateTimeService/" />                      
                    </baseAddresses>
                </host>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <!-- To avoid disclosing metadata information, 
          set the value below to false before deployment -->
                    <serviceMetadata httpGetEnabled="True"/>
                    <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
                    <serviceDebug includeExceptionDetailInFaults="False" />
                </behavior>             
            </serviceBehaviors>
            <endpointBehaviors>
                <behavior name="webHttpBehavior">
                    <webHttp/>
                </behavior>
            </endpointBehaviors>
        </behaviors>
    </system.serviceModel>

So I was curious how complex this will be with WCF. Tried it out. It's streight forward.

I used this tutorial to create a simple service that has a doWork method that expects a string and returns a greeting.

Greeting:

[DataContract]
public class Greeting
{
    [DataMember]
    public string Str { get; set; }
}

Svc Contract:

[OperationContract]
[WebInvoke(Method = "ResponseFormat = WebMessageFormat.BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "sayHello/{name}/")]
Greeting DoWork(string name);

Svc Impl:

public class GreetingService : IGreetingService
{
    public Greeting DoWork(string name)
    {
        return new Greeting {Str = string.Format("Hello {0}", name)};
    }
}

Then you can first test it by:

  • Right click on the svc file in visual studio > view in browser
  • add 'sayHello/test' to the url
  • see the greeting in the browser

A consumer for this can be implemented in AngularJS using either the $http oder the $resource service

<!DOCTYPE html>
<html ng-app="restTest">
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular-resource.min.js"></script>
    <script language="javascript">
        // set up the app
        var app = angular.module('restTest', ['ngResource']);

        // create a controller
        app.controller('RestTestCtrl', function ($scope, $http, $resource) {
            // initial greeting
            $scope.greeting = "Not greeted yet";

            // say hello, consuming the svc using $http
            $scope.sayHelloHttp = function () {
                var url = "http://localhost:7507/GreetingService.svc/sayHello/" + $scope.inName + "/";
                $http.get(url).
                    success(function(data) {
                        $scope.greeting = data.Str;
                    });
            }

            // say hello, consuming the svc using $resource
            $scope.sayHelloRest = function () {
                var GreetingSvc = $resource("http://localhost:7507/GreetingService.svc/sayHello/:name");
                GreetingSvc.get({ name: $scope.inName }, function(data) {
                    $scope.greeting = data.Str;
                });
            }
        });
    </script>
</head>
    <body ng-controller="RestTestCtrl">
        <!-- bind the value of this input to the scope -->
        <input type="text" ng-model="inName"/>
        <button ng-click="sayHelloHttp()">$http</button>
        <button ng-click="sayHelloRest()">$resource</button>
        <!-- bind the greeting property -->
        <div>{{greeting}}</div>
    </body>
</html>

I guess everything above can be expressed more advance but it should give you a basic and working example to get started.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM