dotnet / dotnet/aspnetcore

GenerateCheckBox throws an exception if the URL parameter cannot be parsed to a boolean

Open
#64,739 1 comment 0 reactions 0 assignees View on GitHub
area-mvc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

If `DefaultHtmlGenerator.GenerateCheckBox` is called, and `isChecked` is null, then ASP.NET Core will try to take the value from the ModelState, parse it as a boolean, and use that to populate the checkbox's value. However, if the value in the ModelState cannot be parsed as a boolean, then ASP.NET Core throws a FormatException.

### Expected Behavior

It is surprising that this can cause a FormatException to be thrown, since invalid user input is expected to be discarded when the model is initially bound. I would expect that if the input cannot be parsed, the checkbox is not set. If this is expected behaviour, guidance from the .NET team as to how a developer should handle this would be welcome.

### Steps To Reproduce

Repo: https://github.com/waiwaing/aspnet-checkbox-exception

1. Open http://localhost:5105/Example/Edit?MyBool=false - note page renders correctly
2. Open http://localhost:5105/Example/Edit?MyBool=falsse - note exception is thrown

### Exceptions (if any)
```
System.FormatException: falsse is not a valid value for Boolean.
---> System.FormatException: String 'falsse' was not recognized as a valid Boolean.
at System.Boolean.Parse(ReadOnlySpan`1 value)
at System.Boolean.Parse(String value)
at System.ComponentModel.BooleanConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
--- End of inner exception stack trace ---
at System.ComponentModel.BooleanConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingHelper.ConvertSimpleType(Object value, Type destinationType, CultureInfo culture)
at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingHelper.UnwrapPossibleArrayType(Object value, Type destinationType, CultureInfo culture)
at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingHelper.ConvertTo(Object value, Type type, CultureInfo culture)
at Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GetModelStateValue(ViewContext viewContext, String key, Type destinationType)
at Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GenerateInput(ViewContext viewContext, InputType inputType, ModelExplorer modelExplorer, String expression, Object value, Boolean useViewData, Boolean isChecked, Boolean setId, Boolean isExplicitValue, String format, IDictionary`2 htmlAttributes)
at Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator.GenerateCheckBox(ViewContext viewContext, ModelExplorer modelExplorer, String expression, Nullable`1 isChecked, Object htmlAttributes)
at Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.GenerateCheckBox(ModelExplorer modelExplorer, String expression, Nullable`1 isChecked, Object htmlAttributes)
at Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper`1.CheckBoxFor(Expression`1 expression, Object htmlAttributes)
at Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperInputExtensions.CheckBoxFor[TModel](IHtmlHelper`1 htmlHelper, Expression`1 expression)
at AspNetCoreGeneratedDocument.Views_Example_Edit.ExecuteAsync()
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, Boolean invokeViewStarts)
at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, String contentType, Nullable`1 statusCode)
at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)
at Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|22_0(ResourceInvoker invoker, IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
```

### .NET Version

10.0.100

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.