LP13
LP13

Reputation: 34109

Html does not refresh after ajax post in asp.net core

I have asp.net core application. I am using jQuery ajax to post data to server. When server receives the model, it updates all model properties with timestamp and returns the partial view with updated model. On client side jQuery simply puts the response html inside div

Below is my sample code

Model Class

public class MyModel
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string City { get; set; }
}

Controller

public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View(new MyModel { FirstName = "Foo", LastName = "Bar", City = "Dallas" });
        }        

        public IActionResult PostData(MyModel model)
        {
            model.FirstName = model.FirstName + string.Format(" {0:ss}", DateTime.Now);
            model.LastName = model.LastName + string.Format(" {0:ss}", DateTime.Now);
            model.City = model.City + string.Format(" {0:ss}", DateTime.Now);

            return PartialView("_MyPartialView", model);
        }
    }

Index View

@model MyModel   
<div id="mydetail">
    @Html.Partial("_MyPartialView.cshtml", Model)
</div>

_MyPartialView

@model MyModel

<form id="myform">
    <div class="readonly">
        This is readonly section. This section gets refreshed after POST
        @Model.FirstName
        @Model.LastName
        @Model.City
    </div>
    <div class="row">
        <div class="col-lg-3">
            <input asp-for="FirstName" />
        </div>
        <div class="col-lg-3">            
            @Html.TextBoxFor(x=>x.LastName) 
        </div>
        <div class="col-lg-3">
            <input id="City" name="City" type="text" value="@Model.City" /> 
        </div>
    </div>
    @DateTime.Now.ToString()
</form>

javascript

$(function () {
    var form = $("#myform");
    $('#btn').click(function () {
        $.ajax({
            cache: false,
            type: 'POST',
            url: '/home/postdata',
            data: form.serialize(),
            dataType: 'html',            
            contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
        })
        .done(function (response, textStatus, jqXHR) {
            $('#mydetail').html(response);
        })
        .fail(function (response, textStatus, errorThrown) {
            alert(response);
        })
    })
})

MyModel has 3 properties FirstName, LastName and City. For demonstration purpose i am using 3 different ways to render these properties as TextBox.

Steps

  1. User Clicks on the button to post model to server.
  2. Server gets the model and append the model with timestamp (seconds).
  3. Server returns partial view with updated model.
  4. In read only section partial view writes the properties as text. eg @Model.FirstName, @Model.LastName, @Model.City
  5. Partial view also renders properties as input field. (Note each input field is using different syntax)

Issue
Upon successful POST, when partial view gets rendered then only readonly section and City property gets refreshed and i see updated data. However FirstName and LastName does not get refreshed. Why input field that is using Tag-Helper and Html Helper does not get refreshed?

is this a bug in ASP.NET Core?

Upvotes: 2

Views: 3293

Answers (2)

bvoleti
bvoleti

Reputation: 2552

Frank's answer addresses the issue and using ModelState.Clear(); will get the example to work as expected.

After looking into the source, here is why I think this works: HtmlHelper generates the input tag using DefaultHtmlGenerator. It uses GenerateInput method which first attempts to get value from ModelState and if no value is found [that is the case after ModelState.Clear();] then it uses the current model value.

Relevant code below from source:

case InputType.Text:
    default:
        var attributeValue = (string)GetModelStateValue(viewContext, fullName, typeof(string));
        if (attributeValue == null)
        {
            attributeValue = useViewData ? EvalString(viewContext, expression, format) : valueParameter;
        }       

Upvotes: 0

Frank Fajardo
Frank Fajardo

Reputation: 7359

Try clearing your model state, by calling ModelState.Clear() before you update your model during a Post action method. This will make the input elements in your (partial) view reflect any changes to the model.

I think your scenario is the same as what I encountered in an SO question I posted 3 years ago and here's the answer I got

ModelState.Clear() is required to display back your model object

Upvotes: 3

Related Questions