I explicitly added the [AllowAnonymous]
annotation at controller level because I need this very problem to not be happening, however when I post to the controller, I get a CORS error:
Access to fetch at ‘https://login.microsoftonline.com//oauth…&x-client-SKU=ID_NET6_0&x-client-ver=6.21.0.0’ (redirected from ”) from origin ” has been blocked by CORS policy…
To my understanding, this definitely should not be happening (and doesn’t happen on other POST actions to the same controller just by the way).
I don’t understand where the problem is or how to fix it.
[AllowAnonymous]
[ApiController]
[Route("api/[controller]")]
public class MembersController : ControllerBase
[HttpPost]
public async Task<IActionResult> CreateMemberAsync(CreateMemberViewmodel model)
{
if (!model.IsValid(out List<string> validationResult))
{
return BadRequest(new { Success = false, Errors = validationResult });
}
if (memberService.Exists(model, out Member _))
{
var failResult = new { Success = false, Errors = new List<Exception> { new("Unable to create member; member already exists.") } };
return BadRequest(failResult);
}
var result = await memberService.CreateAsync(model, User);
return Ok(new { Success = true, Values = new [] { result }});
}
[HttpPost("Suggest")]
public async Task<IActionResult> SuggestMembersAsync(CreateMemberViewmodel member)
{
var phoneNumberUtil = PhoneNumberUtil.GetInstance();
try
{
var phoneNumber = phoneNumberUtil.Parse(member.MobileTel, "ZA");
var intlFormat = phoneNumberUtil.Format(phoneNumber, PhoneNumberFormat.INTERNATIONAL);
member.MobileTel = intlFormat;
}
catch (NumberParseException)
{
var result = new { Success = false, Value = $"Unable to suggest members; submitted mobileTel is invalid: '{member.MobileTel}'"};
return BadRequest(result);
}
var members = await memberService.GetMembersAsync(o => o.OrderBy(x => x.Name));
members = members.Where(x =>
(x.Name.Trim() + " " + x.Surname.Trim()).ToLower().Contains((member.Name + " " + member.Surname).ToLower()) ||
x.Email.ToLower().Trim().Contains(member.Email.ToLower().Trim()) ||
x.MobileTel.Contains(member.MobileTel)
).ToList();
return Ok(new { Success = true, Values = members });
}
I’ve only included 2 of the POST actions on the controller for brevity.
The [HttpPost("Suggest")]
action which retrieves a list of members whose PII is the same as what was submitted works, but the [HttpPost]
method which saves a new member anyway, doesn’t.
The javascript fetch requests to these actions are basically identical:
function getMemberSuggestions(member, containerParent) {
fetch(`https://<api url>/api/Members/Suggest`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(member)
})
.then(res => res.json())
.then(data => {
...
})
function saveMember(member)
{
fetch(`https://<api url>/api/Members`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(member)
})
.then(res => res.json())
.then(data => {
if (data.success) {
// Redirect to the Calendar with the new member preloaded.
location.href = `/Home/${data.values[0].id}`
}
else
{
console.error("Failed to save member.")
data.errors.forEach(error => console.error(error))
}
})
}
I don’t get why the “Suggest” endpoint doesn’t route the request through authorization, but the unnamed endpoint does.
I’ve added CORS on the api project:
services.AddCors(options =>
{
options.AddPolicy("SignalRPolicy",
builder => builder.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins(
"https://localhost:5001", // Self
"https://localhost:5003", // Bookings Portal
"https://localhost:7008", // Providers Portal
"https://localhost:7060", // Patients Portal
"https://localhost:7066", // Reports Portal
"https://localhost:7093", // Amani Portal
// Live URLs go here as well
)
.AllowCredentials());
});
So what gives? How do I get around this CORS issue?