Home > Software engineering >  razor pages BindProperty not working on hidden peroperties
razor pages BindProperty not working on hidden peroperties

Time:08-02

From the below models ReportType_AdHoc & ReportType_PushReport are properly binded so that when OnPost() occurs, these values are persistent from what was selected on screen. However, the Pager properties are not even though I tried including them as hidden fields inside the form but that doesn't seem to help? I always see error "pager == null". What am I doing wrong with BindProperty - How can I make the Pager class properties persistent?

My Models:

public class MyReportModel
{
    public MyReportParams myReportParams { get; set; }
    public Pager pager { get; set; }
    public IEnumerable<Reports> results { get; set; }
}

public class Pager
{
    public float pageResults { get; set; } = 100f;
    public double pageCount { get; set; }
    public int pageNumber { get; set; }
    public int resultsCount { get; set; }
}
public class MyReportParams
{
    [Display(Name = "AdHoc")]
    public bool ReportType_AdHoc { get; set; };
    [Display(Name = "Push Report")]
    public bool ReportType_PushReport { get; set; };
}

Index.cshtml.cs

public class IndexModel : PageModel
{
    . . .

    [BindProperty]
    public  MyReportModel myReportModel { get; set; }

    . . .
    public async Task<IActionResult> OnPost()
    {
        if (myReportModel.myReportParams == null)
             _logger.LogInformation("myReportParams == null");
        if (myReportModel.pager == null)
             _logger.LogInformation("pager == null");
        . . .
    }

    . . .
}

Index.cshtml

<form method="post">

  . . .

  <input type="hidden" name="myReportModel" asp-for="myReportModel" />
  <input type="hidden" name="pager"  asp-for="myReportModel.pager" />
  <input type="hidden" name="pageCount"  asp-for="myReportModel.pager.pageCount" />
  <input type="hidden" name="resultsCount"  asp-for="myReportModel.pager.resultsCount" />
  <input type="hidden" name="pageNumber"  asp-for="myReportModel.pager.pageNumber" />
  <input type="hidden" name="pageResults"  asp-for="myReportModel.pager.pageResults" />

  . . .

  <div >
      <div >
          <h6 >Report Type:</h6>
      </div>
      <div >
          <div >
              <div >
                  <input  type="checkbox" asp-for="myReportModel.myReportParams.ReportType_AdHoc">
                  <label  asp-for="myReportModel.myReportParams.ReportType_AdHoc"></label>
              </div>
          </div>
          <div >
              <div >
                  <input  type="checkbox" asp-for="myReportModel.myReportParams.ReportType_PushReport">
                  <label  asp-for="myReportModel.myReportParams.ReportType_PushReport"></label>
              </div>
          </div>
      </div>
  </div>
  . . .
</div>

CodePudding user response:

1.Be sure the hidden inputs contain value(press F12 in the browser and check the Elements).

2.Model Binding binds the property by name attribute. asp-for will generate the name attribute, but if you specify the name it will override tag helper generated name.

3.myReportModel.pager.propertyName is the correct name for binding. Just remove the name attribute in each input element will works fine. Besides, input with asp-for="myReportModel" and asp-for="myReportModel.pager" are useless. Tag helper cannot generate the value for the complex model. Suggest you can remove them:

<form method="post">
    @*<input type="hidden" name="myReportModel" asp-for="myReportModel" />
    <input type="hidden" name="pager"  asp-for="myReportModel.pager" />*@
    <input type="hidden"  asp-for="myReportModel.pager.pageCount" />
    <input type="hidden"  asp-for="myReportModel.pager.resultsCount" />
    <input type="hidden"  asp-for="myReportModel.pager.pageNumber" />
    <input type="hidden"  asp-for="myReportModel.pager.pageResults" />

    <div >
        <div >
            <h6 >Report Type:</h6>
        </div>
        <div >
            <div >
                <div >
                    <input  type="checkbox" asp-for="myReportModel.myReportParams.ReportType_AdHoc">
                    <label  asp-for="myReportModel.myReportParams.ReportType_AdHoc"></label>
                </div>
            </div>
            <div >
                <div >
                    <input  type="checkbox" asp-for="myReportModel.myReportParams.ReportType_PushReport">
                    <label  asp-for="myReportModel.myReportParams.ReportType_PushReport"></label>
                </div>
            </div>
        </div>
    </div>
    <input type="submit" value="post" />
</form>

Result:

enter image description here

CodePudding user response:

Model binding can be a little weird, particularly if you don't provide any explicit [BindProperty(Name = "...")]. Or when you don't use name prefixes in your form values.

At each level of your model, if no value is found with the name of the property, the model binder will attempt to bind the object from an empty prefix.

This can cause some weird model binding errors. Particularly noticeable when you have a collection property to bind, but don't provide any actual values for that collection.

Since you have provided an explicit value for name="pager", even though it is a class and has no value itself, all child properties must have that name as a prefix. Either as dot or array notation. eg name="pager.pageCount".

You'll find it much easier to just let the asp-for="..." tag helper define all the input names. Using explicit BindProperty attributes if you wish to override them.

  • Related