Alpha977
Alpha977

Reputation: 53

How to Call Api Controller from another Api Controller In Same Project

i have an object "ApplicantDetail" with list of objects in ApplicantController and i want to send Post Request to Personaldetails Api On To save into database and get response back

Api On ApplicantController

    // POST: api/ApplicantDetail
    [HttpPost]
    [Route("~/api/ApplicantDetail")]
    public IActionResult Post([FromBody] Personaldetail ApplicantDetail)
    {

        Personaldetail personaldetail = new Personaldetail
        {
            Name = ApplicantDetail.Name,
            Cnic = ApplicantDetail.Cnic,
            Phone = ApplicantDetail.Phone
        };

        List<Address> addresses = new List<Address>();
        List<Employee> employees = new List<Employee>();
        List<Bank> banks = new List<Bank>();

        addresses.AddRange(ApplicantDetail.Address);
        employees.AddRange(ApplicantDetail.Employee);
        banks.AddRange(ApplicantDetail.Bank);

        var response = *//How to Call Personaldetail Post APi of PersonaldetailController Controller From Here and Get 
          response back//*

        return null;
    }

Api On Personaldetail Controller

    // POST: api/Personaldetails
    [HttpPost]
    public async Task<IActionResult> PostPersonaldetail([FromBody] Personaldetail personaldetail)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        _context.Personaldetail.Add(personaldetail);
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetPersonaldetail", new { id = personaldetail.ApplicantId }, personaldetail);
    }

Upvotes: 4

Views: 13446

Answers (4)

Sreekanth
Sreekanth

Reputation: 395

I could see that your target method (PostPersonaldetail) on controller2 (Personaldetail Controller) is an asynchronous method. While we are calling it we need to use the await keyword with async applied to the method (POST: api/ApplicantDetail) as we can't use await keyword in a method with out making the method as async. Alternatively we can apply wait on the method call too.

Controllers are nothing but classes, we can create an instance and call methods defined in it, however it's not a good practice. Using dependency injection we can get references to other services/controllers with in the application and use it to call methods defined on them.

Approach 1:

 public async IActionResult Post([FromBody] Personaldetail ApplicantDetail)
 {
    var response = await new controller2().PostPersonaldetail(persondetails);
 }

Approach 2:

 public IActionResult Post([FromBody] Personaldetail ApplicantDetail)
 {
    var response = new controller2().PostPersonaldetail(persondetails).Wait();
 }

The following links can be helpful.

Resource 1

Resource 2

Upvotes: 0

Stefan
Stefan

Reputation: 17658

If this is within the same process it's unwise to call a controller from another controller.

It's more common to create a class, usually called a service, in which you put your logic to apply the task at hand.

This will have some benifits:

  • isolation of the logic
  • not having to worry about it when changing one endpoint
  • not worry about changing url's or authentication
  • not having an unnecessary network action

E.g.:

The service:

public class YourService
{
    public void YourMethod(parameters)
    {
       //do your stuff
    }
}

The usage:

public class Controller1 : Controller
{
    public void YourAction1()
    {
        //controller specific stuff like model validation      

        //shared logic
        var service = new YourService();
        service.YourMethod();
    }
}

public class Controller2 : Controller
{
    public void YourAction2()
    {
        //controller specific stuff like model validation      

        //shared logic
        var service = new YourService();
        service.YourMethod();
    }
}

Alternativly you can use a DI framework to resolve your service.

Upvotes: 3

JackSojourn
JackSojourn

Reputation: 364

I don't think you want to new up an instance because it could be missing dependencies. You can do something like:

var controller = DependencyResolver.Current.GetService<PostPersonaldetail>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, controller);

Then make the call.

You could also use dependency injection and just have a reference in the controller:

class ApplicantController : ControllerBase
{
    public ApplicantController(ControllerB controllerb)
    {
        _contollerB = controllerB;
    }

you may have to add a call to add the transient service:

services.AddTransient<ControllerB>();

Upvotes: -1

Chris Pratt
Chris Pratt

Reputation: 239300

You should create a service class to represent the personal details API. In this class, you would inject HttpClient, and then set up IHttpClientFactory with a strongly-typed client:

public class PersonalDetailsService
{
    private readonly HttpClient _client;

    public PersonalDetailsService(HttpClient client)
    {
        _client = client;
    }

    // methods here to interact with API via `_client`
}

Then, in ConfigureServices:

services.AddHttpClient<PersonalDetailsService>(c =>
{
    c.BaseAddress = new Uri(Configuration["PersonalDetailsAPIUrl"]);
    // configure anything else you need to on the `HttpClient`
});

Finally, in your controller, you inject PersonalDetailsService:

[ApiController]
[Route("api/ApplicantDetail")]
public class ApplicantController
{
    private readonly PersonalDetailsService _personalDetailsService;

    public ApplicantController(PersonalDetailsService personalDetailsService)
    {
        _personalDetailsService = personalDetailsService;
    }

    [HttpPost("")]
    public async Task<IActionResult> Post([FromBody] Personaldetail ApplicantDetail)
    {
        ...

        var response = await _personalDetailsService.SomeMethodAsync(someParam);

        return null;
    }
}

Upvotes: 5

Related Questions