Home > Software engineering >  Why model is losing it's binded data in Razor pages?
Why model is losing it's binded data in Razor pages?

Time:05-27

I have two questions related to following code I am binding User in OnGet method which works fine, let's say User.Id is 5 and name is "TestGuy". Then after site is fully loaded and i call OnPost method, User.Id becomes the same as "id" for a product in OnGet parameter i am passing, and User.name is null. In order to retrieve that user in OnPost i must duplicate code and again query for him trough SignInManager the same way i do that in OnGet, and it feels just wrong.

  1. So my first question is: Why this is happening. Why UserModel User is losing his data after page is loaded/? I even tried decorating it with supportGet = true

  2. Then second question. In OnGet method when i have this line :

    ProductToBorrow = products[id - 1];

I must subtract 1 from id to match them because ProductToBorrow.ID is always bigger by 1 than id in products and i cannot understand why. I looked trough my code and there is no code which could cause that addition on ProductToBorrow.

   public class RentProductModel : PageModel
    {
    private readonly SignInManager<IdentityUser> _signInManager;
    public RentProductModel(SignInManager<IdentityUser> signInManager)
    {
        _signInManager = signInManager;
    }

    [BindProperty] public ProductModel ProductToBorrow { get; set; } = new();
    public List<ProductModel> UserProducts { get; set; } = new();
    public DateSelector dateSelector { get; set; } = new();
    [BindProperty] public UserModel User { get; set; } = new();



    public IEnumerable<SelectListItem> Days { get; set; } 
    public ApiManager apiManager { get; set; } = new();


    public async Task<IActionResult> OnGetProduct(int id)
    {
        var currentUser = await _signInManager.UserManager.GetUserAsync(HttpContext.User);
        var users = await apiManager.GetUsers();
        User = users.FirstOrDefault(u => u.UserName == currentUser.UserName);

        var products = await apiManager.GetProducts();
        UserProducts = products.Where(x => x.Lent).Where(p => p.UserId == User.Id).ToList();

         ProductToBorrow = products[id - 1];

        Days = dateSelector.OptionListDays();



        return Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        var currentUser = await _signInManager.UserManager.GetUserAsync(HttpContext.User);
        var users = await apiManager.GetUsers();
        User = users.FirstOrDefault(u => u.UserName == currentUser.UserName);

        //update product
        ProductToBorrow.Lent = true;
        ProductToBorrow.LoanDateTimeStart = DateTime.Now;
        Convert.ToDateTime(ProductToBorrow.LoanDateTimeEnd);

        ProductToBorrow.UserId = User.Id;
   

        if (ModelState.IsValid)
        {
             await apiManager.UpdateProduct(ProductToBorrow);
            TempData["success"] = "Product has been succesfully booked.";
        }


        return RedirectToPage("/Search");


    }
}

I added following code but AllProducts have 0 objects in OnPost handler (picture)

       </div>
        <form method="post">
                @foreach (var product in Model.AllProducts)
                {
                    <input type="hidden" asp-for="@product.Id"/>
                    <input type="hidden" asp-for="@product.Type"/>
                    <input type="hidden" asp-for="@product.Lent" value="false"/>
                    <input type="hidden" asp-for="@product.LoanDateTimeStart" value="null"/>
                    <input type="hidden" asp-for="@product.LoanDateTimeEnd" value="null"/>
                    <input type="hidden" asp-for="@product.Release" value="null"/>
                    <input type="hidden" asp-for="@product.ReleaseId"/>
                    <input type="hidden" asp-for="@product.User" value="null"/>
                    <input type="hidden" asp-for="@product.UserId" value="null"/>
                }
            <div   style="padding: 10px">
                <button type="submit"  asp-page-handler="Reset">RESET PRODUCTS</button>
            </div>
        </form>
    </div>

CodePudding user response:

Try to use the following code to pass data to handler:

@for (var i = 0; i < Model.AllProducts.Count(); i  )
                {
                    <input type="hidden" asp-for="@Model.AllProducts[i].Id"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i].Type"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i].Lent" value="false"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i].LoanDateTimeStart" value="null"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i].LoanDateTimeEnd" value="null"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i].Release" value="null"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i].ReleaseId"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i]t.User" value="null"/>
                    <input type="hidden" asp-for="@Model.AllProducts[i].UserId" value="null"/>
                }
  • Related