I’m working on a ASP.NET 5 Web API project on VS2019. I’m trying to set a breakpoint on the POST action (PostCustomerPayment) in the controller however, the breakpoint is never hit. I tried setting breakpoints in several other areas (such as the GET action and other controllers) and they work just fine. I’ve been trying to figure it out for hours and I even tried repairing visual but no luck. Any help would be really appreciated
Here is the code for the controller:
namespace IcartE1.Controllers.API
{
[Route("api/[controller]")]
[ApiController]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class CustomerPaymentsController : ControllerBase
{
private readonly ApplicationDbContext _context;
private readonly ICipherService _cipherService;
public CustomerPaymentsController(ApplicationDbContext context,ICipherService cipherService)
{
_context = context;
_cipherService = cipherService;
}
// GET: api/CustomerPayments
[HttpGet]
public async Task<ActionResult<IEnumerable<CustomerPayment>>> GetCustomerPayment()
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var payments = await _context.CustomerPayment.Where(cp=> cp.CustomerId==userId).ToListAsync();
foreach(var payment in payments)
{
payment.CardNumber = _cipherService.Decrypt(payment.CardNumber);
}
return payments;
}
// POST: api/CustomerPayments
[HttpPost]
public async Task<ActionResult<CustomerPayment>> PostCustomerPayment([FromForm] CustomerPayment customerPayment)
{
customerPayment.CustomerId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (ModelState.IsValid)
{
customerPayment.CardNumber = _cipherService.Encrypt(customerPayment.CardNumber);
_context.CustomerPayment.Add(customerPayment);
await _context.SaveChangesAsync();
return CreatedAtAction("GetCustomerPayment", new { id = customerPayment.Id }, customerPayment);
}
return ValidationProblem();
}
// DELETE: api/CustomerPayments/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteCustomerPayment(int id)
{
var customerPayment = await _context.CustomerPayment.FindAsync(id);
if (customerPayment == null)
{
return NotFound();
}
_context.CustomerPayment.Remove(customerPayment);
await _context.SaveChangesAsync();
return NoContent();
}
private bool CustomerPaymentExists(int id)
{
return _context.CustomerPayment.Any(e => e.Id == id);
}
}
}
EDIT: Postman Request
The model in question
public class CustomerPayment
{
public int Id { get; set; }
[Required,Display(Name ="Holder Name")]
[RegularExpression(pattern: @"^[a-zA-Z ]+$", ErrorMessage = "Holder name can only contain letters.")]
public string HolderName { get; set; }
[Required,Display(Name ="Card Number")]
[CreditCard]
public string CardNumber { get; set; }
[Required]
public DateTime ExpiryDate { get; set; }
[Required]
public string CustomerId { get; set; }
}
EDIT 2: Because customerId was set as required the action is handled earlier so the request doesn’t hit the controller at all, removing [Required] annotation tag from customerId fixed the problem
2
Answers
Because
customerId
was set as required, the action is handled earlier in the pipeline so the request doesn't hit the controller at all. Removing the[Required]
annotation tag fromcustomerId
fixed the problem.PostCustomerPayment([FromForm] CustomerPayment customerPayment)
I suspect it’s how you are accessing the action. Since you’re using [FromForm], your request should be like;
Try changing it to
[FromBody]
if you’re trying to POST json body.You could read more about model binding here; https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#frombody-attribute