2

Is there a way to call your applications API controller from another class without using the API's url?

For example I have this method in a "personContoller"

    public async Task<ActionResult> GetPersonRecord(string id)
    {
        Person person;
        var link = "api/entity/Person/" + id + "?format=json";
        string results = await OneIMAction(link);
        person = JsonConvert.DeserializeObject<Person>(results);
        string json = JsonConvert.SerializeObject(person, Formatting.Indented);
        return Content(json, "application/json");
    }

How can I access the JSON result from this method in another C# class within the same application without resorting to using a web request? Is that possible?

Heimi
  • 126
  • 1
  • 12
Joshua Fellers
  • 111
  • 3
  • 11
  • 4
    You should hide this implementation behind a Service, and call It where is needed. – Fals Nov 22 '17 at 20:07
  • Something like what this answer is discussing or something else? https://stackoverflow.com/questions/14887871/creating-a-service-layer-for-my-mvc-application – Joshua Fellers Nov 22 '17 at 20:26
  • 1
    Just wondering what the point of deserializing `results` string and the serializing your `person` again? – phuzi Nov 22 '17 at 21:23
  • Good catch phuzi. That was leftover from something else. Its been removed. Thanks. – Joshua Fellers Nov 28 '17 at 20:49

4 Answers4

6

According to the Single Responsibility Principle (the first principle of S.O.L.I.D.), “every module or class should have responsibility over a single part of the functionality provided by the software”.

The class which inherits from the API Controller has to respond to the web requests. If we want an API Controller has access to some action of another API Controller, we should create a web request and call that URL (which is not recommended). In cases we want a task to be called by more than one method, we transfer it to Facade which is known as a class service. And all actions of the API Controllers who want to use it, will use the class service.

public class TestService 
{
    public void Do()
    {
      // ...
    }
}


public class HomeController1 : Controller
{
    public ActionResult Index()
    {
        var service = new TestService();
        service.Do();
        return View();
    }
}


public class HomeController2 : Controller
{
    public ActionResult Index()
    {
        var service = new TestService();
        service.Do();
        return View();
    }
}
Saeb Panahifar
  • 479
  • 1
  • 5
  • 11
0

Even if it were possible, controllers and actions are not intended for being called internally within the code. They are designed to even have http responses, so if you were to call the function you need to look for these responses and have something like a try catch to check for a 200 response.

If you want to reuse the code you need to have the code you are using in another function and keep the controller and action simply for calling the function. I usually have such things inside my business logic.

For instance in your person class, or a class extending the person class you can have the following:

public static Person GetPerson(string id){

}

You can then call this in your controller and api controller.

Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79
  • @Neville Bad idea! You should keep it sepereted as a service. Creating a static method inside the class and coupling Http and serialization is terrible. – Fals Nov 22 '17 at 23:21
  • yes a static method isn't a good idea agreed. I wasn't entirely sure what his constructor is trying to achieve and I was trying to show a sample code somewhere in between what he has written and what exactly i generally write – Neville Nazerane Nov 23 '17 at 01:57
0

why you using web request ? if its a same application you can call one controller to another control

 public class HomeController : Controller
    {
      public async Task<ActionResult> GetPersonRecord(string id)
        {
            PersonController person =new PersonController();
            var Value =person.PersonDetails()
            Value = JsonConvert.DeserializeObject<Person>(results);
            string json = JsonConvert.SerializeObject(person, Formatting.Indented);
            return Content(json, "application/json");
        }
    }



 public class PersonController : Controller
 { 
     [HTTPPOST]
     public void  PersonDetails ( int PersonID)
     { 
       return XXXX;
     } 
 }
Floxy
  • 117
  • 2
  • 10
  • As my PersonController is apart of my API, it returns the Content not void. I think I need to read-up on how "Tasks" work in C#. It is a new concept to me (as is C#). – Joshua Fellers Nov 29 '17 at 15:07
0

This is a interesting. if you simply need to call an "api" controller, as @saeb-panahifar mentioned, you can call the service directly.

But if the whole point is to separate the Frontend from Backend, not only logically but physically like deploying them in different servers, then you need some tool like nswag, to generate a client on the frontend app that can access the api. https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-nswag, then you can do:

await personClient.GetRecord(id)

At the end, the client will do everything for you, it will use HttpClient to make connection, serialize data, etc.

Jaider
  • 14,268
  • 5
  • 75
  • 82