简体   繁体   中英

Html.CheckBoxFor TypeConversition Error

I have a view model:

public class RegisterModel
{
   ...
   public bool Confirmation{ get; set; }
}

I use checkbox helper on my view:

@model RegisterModel

......
@Html.CheckBoxFor(m => m.Confirmation) 

This checkbox html helper creates:

<input id="Confirmation" name="Confirmation" value="true" type="checkbox">
<input name="Confirmation" value="false" type="hidden">

On Controller

[HttpPost]
[ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model)
{
   if (!ModelState.IsValid)
                return View(model);
.....
}

Let's say some user changes values of inputs to 'xxx' and posts it. Therefore, Model is not valid and we return view. After that, Html.CheckBoxFor gives this error:

The parameter conversion from type 'System.String' to type 'System.Boolean' failed.

Inner Exception:

System.FormatException: xxx is not a valid value for Boolean

When we return view: Model.Confirmation value is false but Request["Confirmation"] value is 'xxx' .

This error comes from ValueProviderResult class on ConvertSimpleType method. I think, it tries to convert Request["Confirmation"] value to boolean and it gives error.

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Conversion failure is not fatal")]
private static object ConvertSimpleType(CultureInfo culture, object value, Type destinationType)
{

.....
    TypeConverter converter = TypeDescriptor.GetConverter(destinationType);
    bool canConvertFrom = converter.CanConvertFrom(value.GetType());
    if (!canConvertFrom)
    {
        converter = TypeDescriptor.GetConverter(value.GetType());
    }
    if (!(canConvertFrom || converter.CanConvertTo(destinationType)))
    {
        // EnumConverter cannot convert integer, so we verify manually
        if (destinationType.IsEnum && value is int)
        {
            return Enum.ToObject(destinationType, (int)value);
        }
             string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ValueProviderResult_NoConverterExists,
                                           value.GetType().FullName, destinationType.FullName);
        throw new InvalidOperationException(message);
    }

.....
}

How can I fix or avoid this error?

According to @StephenMuecke this is default behavior. You can check detailed answer

According to @ataravati we should handle this on model.IsValid==false . If model is not valid, We remove the value of checkbox and assign new one. Therefore We don't get any error when we return view.

 if (!ModelState.IsValid)
            {
                bool confirmation;

                bool.TryParse(Request["Confirmation"],out confirmation);
                ModelState.Remove("Confirmation");
                request.Confirmation = confirmation;
                return View(request);
            }

According to @StephenMuecke if checkbox input value is not boolean, the user is malicious for sure. Therefore we redirect user to another action which has tracking/blocking ip algorithm and returns 404 as a view.

  if (!ModelState.IsValid)
            {
                bool confirmation;
                if (bool.TryParse(Request["Confirmation"], out confirmation))
                    return View(request);
                return RedirectToAction("Http404", "Errors"); //This not just redirecting 404, it has also tracking/blocking ip algorithm.
            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM