Home > Software engineering >  Why is not possible to update property on partial view using razor pages and dotnet 6
Why is not possible to update property on partial view using razor pages and dotnet 6

Time:01-26

Why can I not update public List<string> Images property when OnGetAsync method returns the data?

I am trying render the images on my _Carousel partial but public List<string> Images property is still an empty list. I am coming from ReactJs and I am still figuring out how dotNet razor pages works.

Is there any similar functionality in razor pages as useEffect in Reactjs?

namespace WebUI.Pages.Home.Item
{
    public class ItemModel : PageModel
    {
        [BindProperty]
        public List<string> Images { get; set; } = new();
        private readonly ILogger<ItemModel> _logger;
        // private item service ...
        public ItemModel(Logger<ItemModel> logger)
    {
      // Item service
      _logger = logger
    }

        public async Task<IActionResult> OnGetAsync([FromQuery] int id)
        {
            var result = await _itemService.getItemById(id);
            foreach (var item in result.ItemImages)
            {
                Images.Add(item.Url);
                // **Note that I can log item.Url here and it arrives correctly**
            }
            return new JsonResult(result);
        }
    }
}

partial _Carousel.cshtml, @Model.Images.Count() is still 0 even though the Item has been fetched and I can see the log that it has 3 images.

@model WebUI.Pages.Home.Item.ItemModel
@if (@Model.Images.Count() > 0)
{
  <div>URLs: @Model.Images.Count()</div>
}

<div >
  <div id="panel-1" >
    <div >
      <div >
        <div id="carouselExampleFade"  data-ride="carousel">
          // render images from @Model.Images
          <a  href="#carouselExampleFade" role="button" data-slide="prev">
            <span  aria-hidden="true"></span>
            <span >Previous</span>
          </a>
          <a  href="#carouselExampleFade" role="button" data-slide="next">
            <span  aria-hidden="true"></span>
            <span >Next</span>
          </a>
        </div>
      </div>
    </div>
  </div>
</div>
@section Scripts { }

I also added Item.cshtml where partial _Carousel.cshtml is being called to render images.

@page
@using WebUI.Pages.Home.Item
@model WebUI.Pages.Home.Item.ItemModel

<div >
  @Html.Partial("_Carousel", Model)
  <div ></div>
</div>

@section Scripts {
<script src="~/lib/axios/dist/axios.js"></script>
<script>
  $(document).ready(function () {
    var url = document.URL;
    var id = url.split("?")[1].split("=")[1];
    var data = {};
    axios.get(`@Url.Page("/Home/Item")?Id=${id.toString()}`)
      .then((response) => {
        item = response.data;
        var listItem = `
                        <div  style="width: 18rem;" onClick=navigateToItem(${item.Id})>
                                <div >
                                    <h5 >${item.Name}</h5>
                                    <p >${item.Description}</p>
                                </div>
                        </div>`;
        $('.card-group').append(listItem);
      }).catch(error => {
        console.log(error)
      });
  });
</script>
}

What is the razor way of doing this? I should point out that I am new to razor pages. Any suggestions is mostly welcome.

CodePudding user response:

Razor Pages works quite different compared to reactJs. You don't need to use javascript for this. OnGetAsync should not return json. It should return the Page. Your code could look like this:

Item.cshtml.cs:

public class ItemModel : PageModel
{
    private readonly ILogger<ItemModel> _logger;
    // private item service ...

    public ItemModel(Logger<ItemModel> logger)
    {
        // Item service
        _logger = logger
    }

    [BindProperty]
    public Item Item { get; set; }

    public async Task<IActionResult> OnGetAsync(int id)
    {
        Item = await _itemService.getItemById(id);
        
        return Page();
    }
}

Item.cshtml: (using the partial tag helper is better)

@page
@using WebUI.Pages.Home.Item
@model WebUI.Pages.Home.Item.ItemModel

@if (Model.Item != null)
{
  <div >
    <partial name="_Carousel" model="@Model.Item.ItemImages" />
    <div >
      <div  style="width: 18rem;">
        <div >
          <h5 >@Model.Item.Name</h5>
          <p >@Model.Item.Description</p>
        </div>
      </div>
    </div>
  </div>
}

_Carousel.cshtml:

@model List<string>

@if (Model != null && Model.Count > 0)
{
  <div>URLs: @Model.Count</div>
}

...
  • Related