Search code examples
c#.netwcfasp.net-web-api

How do I migrate my WCF service to a .Net Web API?


I have inherited a legacy .NET WCF service. It is currently hosted within an ASP.NET application.

I need to extract this into a separate ASP.NET Web API 2 service. I want to get rid of the WCF service altogether instead of simply wrapping it with the Web API.

I know that if I was using .NET Core it would be a much simpler as I could used Swagger.

Unfortunately this not an option as we are using the standard .NET framework.

I'm using Visual Studio 2019 and using the available templates to create the service framework.

I am running into difficulty creating the correct routing tags. I assume my method calls would be mapped to action verbs.

Here is a sample code block reflecting what my svc.cs file contains:

using System;
using System.Linq;
using System.ServiceModel.Activation;

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SampleService : ISampleService
{
    public Result1 ServiceCallA(string param1, SampleClass1 param2, SampleClass2 param3) {}
    public Result1 ServiceCallB(string param1, string param2, bool param3) {}
    public Result2 ServiceCallC(string param1, string param2) {}
    public Result2 ServiceCallD(string param1) {}
}

Here is a sample block with my Web API definitions:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

public class ClientActivationController : ApiController
{
    [HttpGet]
    [Route("???")]  
    public Result1 ServiceCallA(string param1, SampleClass1 param2, SampleClass2 param3) {}
    
    [HttpGet]
    [Route("???")]
    public Result1 ServiceCallB(string param1, string param2, bool param3) {}

    [HttpGet]
    [Route("???")]  
    public Result2 ServiceCallC(string param1, string param2) {}
    
    [HttpGet]
    [Route("???")]
    public Result2 ServiceCallD(string param1) {}
}

Here is the standard boilerplate template startup code:

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(WebApiConfig.Register);
    }
}

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

I would like to use the HttpClient to access the services from my Winforms apps.

I am not entirely clear how to construct the URL with embedded parameters.

Here is a code snippet for consuming the service:

var uri = new Uri($"{ServiceUrl}/ServiceCallA ?????");
var response = await _client.GetAsync(uri);

if (response.IsSuccessStatusCode)
{
    return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
    return StatusCode(500, "Server error");
}

Solution

  • The default route template here is

    routeTemplate: "api/{controller}/{id}"
    

    So the uri would look like

    var uri = new Uri($"{ServiceUrl}/api/ServiceCallD?id=n");
    

    Using attribute routing, the route attributes should reflect the correct mapping

    [HttpGet]
    [Route("api/sample/{param1}/{param2}")]
    public Result2 ServiceCallC(string param1, string param2) {}
    
    [HttpGet]
    [Route("api/sample/{param1}")]
    public Result2 ServiceCallD(string param1) {}
    

    For additional routes you would create a new route mapping

        config.Routes.MapHttpRoute(
            name: "AnotherApi",
            routeTemplate: "api/{controller}/{param1}/{param2}"
        );
    

    The uri could look like this;

    var uri = new Uri($"{ServiceUrl}/api/ServiceCallC?param1=n&param2=b");
    

    Further examples here; https://stackoverflow.com/a/25162019/1165173

    https://www.tutorialsteacher.com/webapi/parameter-binding-in-web-api