blazorblazor-server-sidecontent-security-policy

Cannot call Blazor hosted API due to CSP


I've got the following API Controller:

[ApiController]
[Route("api")]
public class ItemsController : Controller
{
  private readonly ApplicationDbContext _context;

  public ItemsController(ApplicationDbContext context)
  {
    _context = context;
  }

  [HttpGet("Items")]
  public IEnumerable<Item> Get()
  {
    var items = _context.Items.ToArray();

    return items;
  }

  [HttpPost("Item")]
  public async Task<ActionResult> UpdateEmployee(Item item)
  {
    try
    {
        _context.Items.Add(item);

        var res = await _context.SaveChangesAsync();
        if (res > 0)
            return Ok();
        else return StatusCode(StatusCodes.Status500InternalServerError);
    }
    catch (Exception ex)
    {
        return StatusCode(StatusCodes.Status500InternalServerError,
            "Error updating data");
    }
  }
}

I can call the GET method from Firefox no problem but when I try to call the POST method I get an error about violating "default-src 'none'".

I have then added the following:

app.Use(async (context, next) =>
{
  context.Response.Headers.Append("Content-Security-Policy", "default-src * 'unsafe-inline' 'unsafe-eval'; script-src * 'unsafe-inline' 'unsafe-eval'; connect-src * 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src *; style-src * 'unsafe-inline';");
  await next();
});

But now I get a non-expressive json+problem response and the code is not executed.

I do not know how to proceed from here.

Since I ultimately want to call this from a winforms app I've decided to go ahead and try that:

WebClient client = new WebClient();
client.Headers.Add("Content-Type", "application/json");
var res = client.UploadData("https://localhost:7250/api/Item", "Post", Encoding.UTF8.GetBytes(json));

As in Firefox, the GET request works without issue but the POST request received an error "BAD REQUEST" with no further information.


Solution

  • The CSP error was a red herring.

    The real problem was a non nullable navigation property on the entity framework model class.

    Instead of:

    class Item {
      public int Id { get; set; }
      public ICollection<Other> Others { get; set; } // non-nullable
    }
    

    It should say:

    class Item {
      public int Id { get; set; }
      public ICollection<Other>? Others { get; set; } // nullable
    }
    

    It's unfortunate that blazor doesn't offer more a more helpful error message/response in such scenarios.