Search code examples
c#httpasp.net-corerazor-pagesantiforgerytoken

POSTing large collection from Razor page causes ERROR 400


I'm getting Error 400 when I post a large collection of objects (301 objects) back to the page handler.

Here's the form (trimmed for simplicity):

        <form method="post" asp-page-handler="BuildJsonObject" asp-antiforgery="false">

            @{
                int i = 0;

                foreach (var node in Model.FlattenedNodes)
                {
                   <div class="form-inline mt-1">
                        <input type="hidden" name="FlattenedNodes[@i].Key" value="@node.Key" />
                        <input type="hidden" name="FlattenedNodes[@i].ValueKind" value="@node.ValueKind" />
                        <input type="hidden" name="FlattenedNodes[@i].Level" value="@node.Level" />
                        <input type="hidden" name="FlattenedNodes[@i].Key" value="@node.Key" />
                        <input type="hidden" name="FlattenedNodes[@i].ID" value="@node.ID" />
                        <input type="hidden" name="FlattenedNodes[@i].ParentId" value="@node.ParentID" />
                        <input type="text" class="form-control" name="FlattenedNodes[@i].StringValue" value="@node.StringValue" id="@id" />
                            
                    </div>
                    i++;
                }
                <button type="submit" class="btn btn-primary">Save</button>
            }
        </form>

I applied IgnoreAntiforgeryToken attribute to the PageModel, and the error now not happening but the posted collection is empty.

The collection definition:

    [BindProperty]
    public List<TreeNode> FlattenedNodes { get; set; } = new List<TreeNode>();

Solution

  • I was able to bypass this issue by applying this attribute to the page model:

    [RequestFormLimits(ValueCountLimit = x)]
    

    I set x to int.MaxValue, and the data are posted normally, but I tried with a larger collection (~500 entries), and got this exception.

    InvalidOperationException: Collection bound to 'FlattenedNodes' exceeded MvcOptions.MaxModelBindingCollectionSize (1024). This limit is a safeguard against incorrect model binders and models. Address issues in 'JsonDataTreeVisualizer.TreeNode'. For example, this type may have a property with a model binder that always succeeds. See the MvcOptions.MaxModelBindingCollectionSize documentation for more information.

    to disable this security rule I added this in Startup.ConfigureServices:

    services.AddMvc(options =>
    {
        options.MaxModelBindingCollectionSize = x;
    });
    

    I set x again to int.MaxValue. I also still need to use IgnoreAntiforgeryToken:

    [RequestFormLimits(ValueCountLimit = int.MaxValue)]
    [IgnoreAntiforgeryToken]
    public class IndexModel : PageModel
    {
        .....
    }
    

    Of course, these security rules are made for good reasons, as explained in the above exception message, for example, it prevents denial of service attacks where the attacker could post large data packets and cause bandwidth throttling, but in my case, I'm just using it in a hobby project.