Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exposing a few calls from an existing asp.net-mvc site to other REST clients within an intranet?

I have an existing asp.net-mvc web site and now I need to expose of a few of my calls to external applications that are only used within my site right now. This is all happening within an intranet within my company.

I have read this page which explains Web API versus controller actions as well as this SOF question which seems to have a similar issue but the answers seem a bit outdated. So I am trying to determine given the latest available functionality what is the simplest solution to meet my requirement.

In my case, since I already have the same controller actions used within my current website then WEB API doesn't really make sense but if I google anything around asp.net-mvc authentication or security I only see articles around web API.

Given that, I am trying to figure out best practice for exposing my controller action to another application.

like image 849
leora Avatar asked Dec 19 '15 14:12

leora


Video Answer


3 Answers

In an ideal world you would convert the app to web api controllers as someone else suggested but to be more pragmatic you can implement an interim solution where you expose only the required calls via extending ApiController

You did not mention which version of MVC your current app is using nor did you mention how your current Controllers return data to the web app. I will therefore assume you return data via a view model and razor views. eg:

public class ProductsController : Controller
{
      public void Index()
      { 
            var view = new ProductsListView();
            view.Products = _repository.GetProducts();
            return View(view);
      }
}

Suppose now you want to expose the products list via a REST-like api? First check you have web api installed (via nuget)

Install-Package Microsoft.AspNet.WebApi

(again i'm not sure what ver of asp.net you are on so this process may differ between versions)

Now in your public void Application_Start()

GlobalConfiguration.Configure(WebApiConfig.Register);//add this before! line below
RouteConfig.RegisterRoutes(RouteTable.Routes);//this line shld already exist

and in WebApiConfig

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

I like to create a dedicated folder called ApiControllers and add controllers with the same name; this way you can have controllers with the same names as they are in different namespaces:

namespace YourApp.Web.ApiControllers
{
    [AllowAnonymous]
    public class ProductsController : ApiController
    {
        [HttpGet]
        public HttpResponseMessage Products()
        {
              var result = new ProductResult();//you could also use the view class ProductsListView
              result.Products = _repository.GetProducts();
              return Request.CreateResponse(httpStatusCode, result);
        }
    }
}

You can then access this via yourapp.com/api/products

nb, try to reduce duplication of code inside controllers - this can be acheived by extracting common parts into service classes.

like image 51
wal Avatar answered Oct 23 '22 05:10

wal


While I would highly recommend using a web service architecture, such as Web API or ServiceStack, you can expose controller actions.

You'll first want to decorate the actions with the [AllowAnonymous] attribute. Then, in your web.config you'll need to add the following code block to the configuration section for each action you want exposed.

<location path="ControllerNameHere/ActionNameHere">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>

As you may have guessed, this becomes very repetitive and annoying, which is why web services would be a great choice.

like image 32
Connor Avatar answered Oct 23 '22 07:10

Connor


I had a similar requirement where website 2 needed to call some controller actions from website 1. Since there was no changes in the logic I wanted to avoid the whole rewrite using web API. I created another set of controller and actions that would return Json. The new controller actions would call the original controller actions and then convert the result data to json before returning. The other applications (website 2) would then make http get and post requests to get json data and deserialize it internally. Worked nicely in my case.

I didn't have to put a security layer over the json based actions as they were public, but you might need one to authenticate the requests.

like image 2
TejSoft Avatar answered Oct 23 '22 06:10

TejSoft