locked
razor core.net don't render to table onpost but does render ongetasync RRS feed

  • Question

  • User-1656198708 posted

    <br>
    &lt;p&gt;Edited: I have now included ALL the code.&lt;/p&gt;<br>
    &lt;p&gt;It is probably very straight forward, but I have not been able to google this, probably because I'm new to Razor, and I don't know the term to search for.&lt;/p&gt;<br>
    &lt;p&gt;It is a simple page with at dropdownlist for teams, and when you have selected the team, it shows the players for that team.&lt;/p&gt;<br>
    &lt;ol&gt;<br>
    &lt;li&gt;The ddl with teams renders fine &lt;/li&gt;&lt;li&gt;The table with the players renders fine, when called from OnGetAsync() &lt;/li&gt;&lt;li&gt;But when I try to do it on the OnPost(), I get a result from the database, and the player list gets populated, and in the view in the foreach
    loop I can see the values being assigend, but the browser does not show this change,&amp;nbsp;<br>
    &lt;/li&gt;&lt;li&gt;I noticed that all the examples for OnPost usually redirects to another page, instead of &amp;quot;reloading&amp;quot; the same page, -have I missed something here?&lt;br&gt;<br>
    &lt;br&gt;<br>
    In the view:&amp;nbsp; &lt;/li&gt;&lt;/ol&gt;<br>
    &lt;pre class=&quot;default prettyprint prettyprinted&quot;&gt;&lt;code&gt;&lt;span class=&quot;pln&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;<br>
    &lt;pre class=&quot;prettyprint lang-auto&quot;&gt;@page<br>
    @model rd.Pages.p2.p2Model<br>
    @{<br>
    ViewData[&amp;quot;Title&amp;quot;] = &amp;quot;p2&amp;quot;;<br>
    }<br>
    <br>
    &amp;lt;h1&amp;gt;Index&amp;lt;/h1&amp;gt;<br>
    <br>
    &amp;lt;form&amp;gt;<br>
    @Html.AntiForgeryToken()<br>
    &amp;lt;p&amp;gt;<br>
    <br>
    &amp;lt;select id=&amp;quot;myDropdown&amp;quot; asp-for=&amp;quot;selectedFilter&amp;quot; asp-items=&amp;quot;Model.team&amp;quot; onchange=&amp;quot;sendData()&amp;quot;&amp;gt;<br>
    &amp;lt;option value=&amp;quot;&amp;quot;&amp;gt;Choose a team&amp;lt;/option&amp;gt;<br>
    &amp;lt;/select&amp;gt;<br>
    <br>
    &amp;lt;/p&amp;gt;<br>
    <br>
    @if (Model.player != null)<br>
    {<br>
    &amp;lt;table class=&amp;quot;table&amp;quot;&amp;gt;<br>
    &amp;lt;thead&amp;gt;<br>
    &amp;lt;tr&amp;gt;<br>
    &amp;lt;th&amp;gt;<br>
    @Html.DisplayNameFor(model =&amp;gt; model.player[0].PlayerName)<br>
    &amp;lt;/th&amp;gt;<br>
    &amp;lt;th&amp;gt;<br>
    @Html.DisplayNameFor(model =&amp;gt; model.player[0].PlayerNumber)<br>
    &amp;lt;/th&amp;gt;<br>
    &amp;lt;th&amp;gt;<br>
    @Html.DisplayNameFor(model =&amp;gt; model.player[0].PlayerActive)<br>
    &amp;lt;/th&amp;gt;<br>
    &amp;lt;th&amp;gt;<br>
    @Html.DisplayNameFor(model =&amp;gt; model.player[0].SortOrder)<br>
    &amp;lt;/th&amp;gt;<br>
    &amp;lt;th&amp;gt;<br>
    @Html.DisplayNameFor(model =&amp;gt; model.player[0].Team)<br>
    &amp;lt;/th&amp;gt;<br>
    &amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;<br>
    &amp;lt;/tr&amp;gt;<br>
    &amp;lt;/thead&amp;gt;<br>
    &amp;lt;tbody&amp;gt;<br>
    @foreach (var item in Model.player)<br>
    {<br>
    &amp;lt;tr&amp;gt;<br>
    &amp;lt;td&amp;gt;&lt;br&gt; @*This is being hit on both the OnGet and the OnPost and is assigned value both times but only seen in browser on OnGet*@<br>
    @Html.DisplayFor(modelItem =&amp;gt; item.PlayerName)<br>
    &amp;lt;/td&amp;gt;<br>
    &amp;lt;td&amp;gt;<br>
    @Html.DisplayFor(modelItem =&amp;gt; item.PlayerNumber)<br>
    &amp;lt;/td&amp;gt;<br>
    &amp;lt;td&amp;gt;<br>
    @Html.DisplayFor(modelItem =&amp;gt; item.PlayerActive)<br>
    &amp;lt;/td&amp;gt;<br>
    &amp;lt;td&amp;gt;<br>
    @Html.DisplayFor(modelItem =&amp;gt; item.SortOrder)<br>
    &amp;lt;/td&amp;gt;<br>
    &amp;lt;td&amp;gt;<br>
    @Html.DisplayFor(modelItem =&amp;gt; item.Team.TeamName)<br>
    &amp;lt;/td&amp;gt;<br>
    &amp;lt;td&amp;gt;<br>
    &amp;lt;a asp-page=&amp;quot;./Edit&amp;quot; asp-route-id=&amp;quot;@item.Id&amp;quot;&amp;gt;Edit&amp;lt;/a&amp;gt; |<br>
    &amp;lt;a asp-page=&amp;quot;./Details&amp;quot; asp-route-id=&amp;quot;@item.Id&amp;quot;&amp;gt;Details&amp;lt;/a&amp;gt; |<br>
    &amp;lt;a asp-page=&amp;quot;./Delete&amp;quot; asp-route-id=&amp;quot;@item.Id&amp;quot;&amp;gt;Delete&amp;lt;/a&amp;gt;<br>
    &amp;lt;/td&amp;gt;<br>
    &amp;lt;/tr&amp;gt;<br>
    }<br>
    <br>
    &amp;lt;/tbody&amp;gt;<br>
    <br>
    &amp;lt;/table&amp;gt;<br>
    }<br>
    <br>
    &amp;lt;/form&amp;gt;<br>
    <br>
    <br>
    @section Scripts{ <br>
    &amp;lt;script&amp;gt;<br>
    function sendData() {<br>
    var selectedFilter = &amp;#36;(&amp;quot;#myDropdown&amp;quot;).val();<br>
    &amp;#36;.ajax({<br>
    type: &amp;quot;POST&amp;quot;,<br>
    url: &amp;quot;/p2/p2&amp;quot;,<br>
    data: { selectedFilter: selectedFilter },<br>
    headers: {<br>
    RequestVerificationToken: &amp;#36;('input:hidden[name=&amp;quot;__RequestVerificationToken&amp;quot;]').val()<br>
    },<br>
    <br>
    error: function() {<br>
    alert(&amp;quot;there was an error&amp;quot;);<br>
    }<br>
    });<br>
    }<br>
    &amp;lt;/script&amp;gt;<br>
    }<br>
    &lt;/pre&gt;<br>
    &lt;pre class=&quot;default prettyprint prettyprinted&quot;&gt;&lt;code&gt;&lt;span class=&quot;pln&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;<br>
    &lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;span class=&quot;pln&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;<br>
    &lt;p&gt;In the controller&lt;/p&gt;<br>
    &lt;pre class=&quot;prettyprint lang-auto&quot;&gt;using System;<br>
    using System.Collections.Generic;<br>
    using System.Linq;<br>
    using System.Security.Cryptography.Xml;<br>
    using System.Threading.Tasks;<br>
    using Microsoft.AspNetCore.Mvc;<br>
    using Microsoft.AspNetCore.Mvc.RazorPages;<br>
    using Microsoft.AspNetCore.Mvc.Rendering;<br>
    using Microsoft.EntityFrameworkCore;<br>
    using rd.Models;<br>
    <br>
    namespace rd.Pages.p2<br>
    {<br>
    public class p2Model : PageModel<br>
    {<br>
    public List&amp;lt;Models.Player&amp;gt; player { get; set; }<br>
    public List&amp;lt;SelectListItem&amp;gt; team { get; set; }<br>
    <br>
    <br>
    private readonly rd.Models.rdnewContext _context;<br>
    <br>
    public p2Model(rd.Models.rdnewContext context)<br>
    {<br>
    _context = context;<br>
    }<br>
    <br>
    public async Task OnGetAsync()<br>
    <br>
    {<br>
    team = await _context.Team.Select(a =&amp;gt;<br>
    new SelectListItem<br>
    {<br>
    Text = a.TeamName.ToString(),<br>
    Value = a.Id.ToString()<br>
    }).ToListAsync();&lt;br&gt; //Should not really be bound here, just to prove that it CAN be bound<br>
    player = (from pl in _context.Player where pl.TeamId == 2 select pl).ToList();<br>
    <br>
    <br>
    }<br>
    <br>
    [BindProperty] public string selectedFilter { get; set; }<br>
    <br>
    public async Task OnPost()<br>
    {<br>
    int teamid = int.Parse(selectedFilter);<br>
    <br>
    //This works in the sense that player IS populated with the desired data<br>
    player = await (from pl in _context.Player where pl.TeamId == teamid select pl).ToListAsync();<br>
    <br>
    }<br>
    }<br>
    }&lt;/pre&gt;<br>
    &lt;p&gt;&lt;br&gt;<br>
    &lt;br&gt;<br>
    &lt;/p&gt;<br>
    Monday, July 13, 2020 5:21 PM

Answers

  • User-474980206 posted

    If you want the server to render the page, don’t use Ajax. If you make an Ajax call, then then JavaScript gets the response and must update the dom.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 20, 2020 2:53 AM

All replies

  • User475983607 posted

    We cannot see all the code.  Are you making an AJAX request?  Also, the way the code is written it should cause an error because you do not repopulate the team select.

    Monday, July 13, 2020 5:54 PM
  • User-474980206 posted

    you should use OnPostAsync, but how do you call it? via a form.submit()? ajax?

     

    Monday, July 13, 2020 5:54 PM
  • User-1656198708 posted

    All code is included, yes I'm using AJAX, and that part works just fine. 

    Actually good point regarding the dropdownlist, after the post, I would expect the dropdownlist to be empty, but it is unchanged, -as in the entire page is unchanged.

    There is now more comments in the code where I have put breakpoints, and where I can see that I do get the desired values and it is assigned where it should, except the only time I can see data in the table in the browser is on the OnGet, even if I can see that data is assigend in the view on both the OnGet AND OnPost, it is ONLY the values from the OnGet I can see in the browser

    It is like the assignment on the OnPost, does not "take", or have any effect

    Monday, July 13, 2020 11:32 PM
  • User-1656198708 posted

    Yeah I have also tried OnPostAsync, no difference. Yes I used AJAX

    Monday, July 13, 2020 11:33 PM
  • User2078676645 posted

    HI,

    The Razor page is rendered by the razor engine, but the ajax request doesn't make razor re-render it, so one way to do this is to render the page in jquery as an ajax request to the data.

    <form>
        @Html.AntiForgeryToken()
        <p>
    
            <select id="myDropdown" asp-items="Model.team" data-bind="@Model.selectedFilter"  onchange="sendData()">
                <option value="">Choose a team</option>
            </select>
            @Model.player.Count
        </p>
        <div id="playershow">
            
        </div>
        @if (Model.player != null)
        {
            <table class="table">
                <thead>
                    <tr>
                        <th>
                            @Html.DisplayNameFor(model => model.player[0].PlayerName)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.player[0].PlayerNumber)
                        </th>
                        @*<th>
                            @Html.DisplayNameFor(model => model.player[0].PlayerActive)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.player[0].SortOrder)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.player[0].Team)
                        </th>*@
                        <th></th>
                    </tr>
                </thead>
                <tbody id="originShow">
                    @foreach (var item in Model.player)
                    {
                        <tr>
                            <td>
                                @*This is being hit on both the OnGet and the OnPost and is assigned value both times but only seen in browser on OnGet*@
                                @Html.DisplayFor(modelItem => item.PlayerName)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.PlayerNumber)
                            </td>
                            @*<td>
                                @Html.DisplayFor(modelItem => item.PlayerActive)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.SortOrder)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Team.TeamName)
                            </td>*@
                            <td>
                                <a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> |
                                <a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
                                <a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
                            </td>
                        </tr>
                    }
    
                </tbody>
                <tbody id="changeShow">
                    
                </tbody>
    
            </table>
        }
    
    </form>
    
    
    @section Scripts{
        <script>
            function sendData() {
                var selectedFilter = $("#myDropdown").val(); console.log(selectedFilter)
                $.ajax({
                    type: "POST",
                    url: "/p2",
                    data: { selectedFilter: selectedFilter },
                    headers: {
                        RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val()
                    },
                    success: function (data) {
                        $("#changeShow").empty();
                        var players = JSON.parse(data);
                        console.log(players)
                        $("#originShow").hide();
                        $("#changeShow").show();
                        
                        for (var i = 0; i < players.length; i++) {
                            $("#changeShow").append('<tr><td>' + players[i].PlayerName + '</td><td>' + players[i].PlayerNumber +'</td></tr>');
                        }
                    },
                    error: function(e) {
                        alert("there was an error--");
                    }
                });
            }
        </script>
    }

    At the same time, OnPost needs to respond with a string in json format.

    public async Task OnPost()
            {
                int teamid = int.Parse(selectedFilter);
                //This works in the sense that player IS populated with the desired data
                player = await (from pl in _context.Player where pl.TeamId == teamid select pl).ToListAsync();
                Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(player));
            }

    Best Regards,

    Evern

    Tuesday, July 14, 2020 7:09 AM
  • User-1656198708 posted

    Well that essentially did the trick, but not exactly the way I had wanted.

    1) The original rendered html is still there, is is just hidden.

    2) The data is "brute force directly appended" by javascript, and not "bound by the system", as I know it can do on the OnGet 

    If you look at my OnGet method, you can see that player list is being populated, and subsequently the view is looping through the list, and values are assigned, and I can see the resulting html just as expected.

    The exactly same happens in the OnPost method, a player list is being populated with different values, and the view is looping through the new values. 
    (And that lead me to believe that this was razor re-render the page, but apparently that is not the case. I have a feeling that I'm missing something important here)

    But the resulting HTML is not changed at all on the OnPost


            public async Task OnGetAsync()
            {
                team = await _context.Team.Select(a =>
                    new SelectListItem
                    {
                        Text = a.TeamName.ToString(),
                        Value = a.Id.ToString()
                    }).ToListAsync();
    
                player = (from pl in _context.Player where pl.TeamId == 2 select pl).ToList();
            }

    Tuesday, July 14, 2020 8:04 AM
  • User475983607 posted

    2) The data is "brute force directly appended" by javascript, and not "bound by the system", as I know it can do on the OnGet 

    The POST response is returned to the AJAX function.   It is up to you to design JavaScript that writes the POST response to the page.  This is a well known and fundamental concept. 

    Tuesday, July 14, 2020 10:26 AM
  • User-1656198708 posted
    But I would prefer NOT to get the respose returned to the Ajax function. As in my original code posted.

    I would like the controller to ( re-)render the page, just as it does on the OnGet.

    This is the usual approach with Asp.mvc, is it very different with core & razor

    And it SEEMS like it is rendered, it loop through the view again, with the new values from the database.

    But there is no change in the resulting HTML.


    Sunday, July 19, 2020 5:07 PM
  • User475983607 posted

    But I would prefer NOT to get the respose returned to the Ajax function. As in my original code posted.

    I would like the controller to ( re-)render the page, just as it does on the OnGet.

    This is the usual approach with Asp.mvc, is it very different with core & razor

    And it SEEMS like it is rendered, it loop through the view again, with the new values from the database.

    But there is no change in the resulting HTML.


    My best guess is you're asking how to return partial content.   See the following blog to understand how to return partial page in Razor Pages.

    https://www.learnrazorpages.com/razor-pages/partial-pages

    Sunday, July 19, 2020 5:37 PM
  • User-474980206 posted

    If you want the server to render the page, don’t use Ajax. If you make an Ajax call, then then JavaScript gets the response and must update the dom.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 20, 2020 2:53 AM