Andrew Simpson
Andrew Simpson

Reputation: 7324

How to test and call my api in external DLL

Using ASP.NET Core 2.0 for 1st time.

I have a web project which references a DLL that i have created.

In this DLL is a simple method...

namespace InformedWorkerApi
{
    [Route("api/[controller]")]
    public class RegistrationController: Controller
    {
        private readonly IAccountRepository _accountRepository;
        public RegistrationController(IAccountRepository accountRepository)
        {
            _accountRepository = accountRepository;
        }

        [HttpPost()]
        [Route("SignOn")]
        public async Task<InformedWorkerModels.Account> SignOn([FromBody]SignOnRequest model)
        {
            return await _accountRepository.SignOn(model.EmailAddress, model.Password);
        }
    }
}

I have also created a test project which references my DLL...

    [TestMethod]
    public async Task SignOn()
    {

        var webHostBuilder = new WebHostBuilder()
            .UseStartup<Startup>();

        using (var host = new TestServer(webHostBuilder))
        {
            using (var client = host.CreateClient())
            {
                var requestData = new SignOnRequest { EmailAddress = "emailAddress", Password= "password" };
                var content = new StringContent(JsonConvert.SerializeObject(requestData), Encoding.UTF8, "application/json");
                var response = await client.PostAsync("api/Registration/SignOn", content);
                //do some asserts here
            }
        }
    }

I get the error status code 404 not found.

What am i getting so wrong here please?

Upvotes: 0

Views: 2430

Answers (1)

Nkosi
Nkosi

Reputation: 247153

You have email and password as part of the route but send them as content in the body. that wont match the route template for the action and thus 404 Not Found.

Create a model to hold the data

public class SignOnRequest {
    [Required]
    public string emailAddress { get; set; }
    [Required]
    public string password { get; set; }
}

Also for core you have to specify with parameter attributes where the framework should look for parameters.

[Route("api/[controller]")]
public class RegistrationController : Controller{

    [HttpPost()]
    [Route("SignOn")] // Matches POST api/Registration/SignOn
    public async Task<IActionResult> SignOn([FromBody]SignOnRequest model) {
        if(ModelState.IsValid) {                
            var response = await _accountRepository.SignOn(model.emailAddress, model.password);
            return Ok(response);
        }
        return BadRequest();
    }
}

Which should now match the request being made in the integration test

var requestData = new { emailAddress = "emailAddress", password = "password" };
var content = new StringContent(JsonConvert.SerializeObject(requestData), Encoding.UTF8, "application/json");
var response = await client.PostAsync("api/Registration/SignOn", content);

As you also mentioned that the controller is in another assembly you would need to make sure that the controller is registered with the ServiceCollection within Startup so that the framework is aware of how to resolve the controller. Update the ConfigureServices to include

services.AddMvc()
  .AddApplicationPart(typeof(RegistrationController).GetTypeInfo().Assembly)
  .AddControllersAsServices();

as referenced from the following answer ASP.NET Core MVC controllers in separate assembly

Upvotes: 1

Related Questions