locked
Data get's cleaned(deleted) after HttpPost to Controller. RRS feed

  • Question

  • User-1714333915 posted

    I have a simple input field that have JS Autocomplete script attached.

    JS script:

    <script type="text/javascript">
    
    $(document).ready(function () {
    $("#UserName").autocomplete({
    source: function (request, response) {
    $.ajax({
    url: "/Users/AutoComplete",
    type: "POST",
    dataType: "json",
    data: { Prefix: request.term },
    success: function (data) {
    response($.map(data, function (item) {
    return { label: item.UserName, value: item.UserName };
    }))
    
    }
    })
    },
    messages: {
    noResults: "", results: ""
    }
    });
    })
    </script>

    Which do it's job.

    Second is the actual field:

    @using (Html.BeginForm(FormMethod.Post))
    {
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
    <hr />
    <div class="form-group">
    <div class="col-md-12">
    @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
    </div>
    </div>
    <div class="form-group">
    <input type="submit" value="Confirm" class="btn btn-primary" />
    </div>
    </div>
    
    <p>The Selected User Name: @Model.UserName</p>
    }

    This is the Controller Post:

    [HttpPost]
    public IActionResult Main(MainUsertModel mod)
    {
    
    // This one only one data that actualy excists
    System.Diagnostics.Debug.WriteLine("This is string Name that was selected " + mod.UserName);
    
    
    // This one already null
    System.Diagnostics.Debug.WriteLine("UserName of the User from WalletData " + mod.UserData.Email);
    
    
    return View(mod);
    }

    Can someone please give me some tip why the Main model that comes from HttpPost loses all data except one mod.UserName

    I Would mostly use standart <form asp-action="ActionName">etc</form> but here I wanted to implement Autocomplete JS script And it is not attachable to <input asp-for="Data"/> field.

    Stuck with this for a few days already.

    Tuesday, July 16, 2019 12:13 PM

Answers

  • User475983607 posted

    The variable UserName is assigned but all the others become null after a HttpPost.

    Correct, the View is designed to submit the Username only.  The View does not submit the UserDataModel or UserHistory properties therefore the model binder cannot populate these properties.  Please see the model binding link above for more information.

    You'll need to lookup the UserDataModel or UserHistory properties in the [HttpPost] Main() action or change the View design.  The main issue seems you think the model values should persist.  As you've experienced values do not automatically persist. It is up to you to write code to handle state.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, July 16, 2019 2:31 PM

All replies

  • User753101303 posted

    Hi,

    The model is populated from values posted by the incoming http request (and for now you have nothing else than the UserName form field ??) Depending on what you want to do you could reload UserData from the database (but for now you are doing nothing special with the Email).

    Edit: try https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-2.2 for details about that...

    Tuesday, July 16, 2019 12:29 PM
  • User-1714333915 posted

    Hi,

    The model is populated from values posted by the incoming http request (and for now you have nothing else than the UserName form field ??) Depending on what you want to do you could reload UserData from the database (but for now you are doing nothing special with the Email).

    Edit: try https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-2.2 for details about that...

    Thank you for your reply.

    I didn't show the full View code it have the @Model.UserData.Email attached at the start of the View file. And it throws NullReference if click Post.

    For now I want to achieve is to show the name that user selects in this field 

    <p>The Selected User Name: @Model.UserName</p>

    Yeap you right I can query second time for data. This will be a bad practice(atleast I think so) it will damage performance especially if I going to use big database.

    The final mission for me is to understand how to pass data from get to post, so I don't need to query second time and understand why this action:

    @using (Html.BeginForm(FormMethod.Post))
    {
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
    <hr />
    <div class="form-group">
    <div class="col-md-12">
    @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
    </div>
    </div>
    <div class="form-group">
    <input type="submit" value="Confirm" class="btn btn-primary" />
    </div>
    </div>
    
    <p>The Selected User Name: @Model.UserName</p>
    }

    Actually deletes all data from MainModel class, and lefts it only with one string that goes to input field.

    Tuesday, July 16, 2019 12:45 PM
  • User475983607 posted

    The code is incomplete and the problem you are trying to solve is not very clear.  At first I thought the issue was with the auto-complete.  Now it seems the issue is doing a full HTTP Post?  If so, you did not share the model; MainWalletModel.  I assume the form post input names does not match MainWalletModel property names.

    Secondly, there is no indication if we are looking at the "Main" View markup.

    Is there anyway you can share enough code to reproduces this issue?

    Tuesday, July 16, 2019 12:58 PM
  • User-1714333915 posted

    Here is the full code of the View:

    @model MainUserModel
    
    @{
        ViewData["Title"] = "Main";
    }
    
    
    <div class="alert-light">
        <div class="text-left text-dark alert-info">Name: @Model.UserData.UserName</div>
        <div class="text-right text-dark alert-info">Email: @Model.UserData.Email</div>
        <div class="btn btn-primary text-dark">
            <a asp-controller="Login" asp-action="SignOut">Sign Out</a>
        </div>
    </div>
    
    <div>
        <p class="text-center">Input Name of the User</p>
        <script type="text/javascript">
    
            $(document).ready(function () {
                $("#UserName").autocomplete({
                    source: function (request, response) {
                        $.ajax({
                            url: "/User/AutoComplete",
                            type: "POST",
                            dataType: "json",
                            data: { Prefix: request.term },
                            success: function (data) {
                                response($.map(data, function (item) {
                                    return { label: item.UserName, value: item.UserName };
                                }))
    
                            }
                        })
                    },
                    messages: {
                        noResults: "", results: ""
                    }
                });
            })
        </script>
        @using (Html.BeginForm(FormMethod.Post))
        {
            @Html.AntiForgeryToken()
            <div class="form-horizontal">
                <hr />
                <div class="form-group">
                    <div class="col-md-12">
                        @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } })
                    </div>
                </div>
                <div class="form-group">
                    <input type="submit" value="Confirm" class="btn btn-primary" />
                </div>
            </div>
    
            <p>The Chosen Name: @Model.UserName</p>
        }
    </div>

    This is the full code of the View.

    Here is the code of the controller Get and Post parts.

    DataModel it is MainUserModel class

    Get:

            [HttpGet]
            public IActionResult Main()
            {
                // Getting User Data from cookie
                string Email = HttpContext.User.Claims.FirstOrDefault(o => o.Type == ClaimTypes.Email).Value;
    
                DataModel.UserData = qUser.QUserData.Where(o => o.Email == Email).FirstOrDefault();
    
                return View(DataModel);
            }

    And the Post part:

    [HttpPost]
    public IActionResult Main(MainUserModel mod)
    {
    
    // This one only one data that actualy excists
    System.Diagnostics.Debug.WriteLine("This is string Name that was selected " + mod.UserName);
    
    
    // This one already null
    System.Diagnostics.Debug.WriteLine("UserName of the User from WalletData " + mod.UserData.Email);
    
    
    return View(mod);
    }

    Also the Data Model of the MainUsertModel:

    public class MainUserModel
        {
            public string UserName { get; set; }
            public UserDataModel UserData { get; set; }
    public UserHistory UserHistory { get; set; } }

    The variable UserName is assigned but all the others become null after a HttpPost.

    Also The UserName from tis part of code: @Html.EditorFor(model => model.UserName, new { htmlAttributes = new { @class = "form-control" } }) is assigned in JsonFunction witch code I also show here:

    public async Task<JsonResult> AutoComplete(string Prefix)
            {
                JsonSerializerSettings settings = new JsonSerializerSettings();
    
    
                List<MainUserModel> mainModels = new List<MainUserModel>();
                foreach(var zx in qUser.QUserData.ToList())
                {
                    mainModels.Add(new MainUserModel { UserName = zx.UserName });
                }
    
    
                var UsersList = from N in mainModels where N.UserName.StartsWith(Prefix) select new { N.UserName };
    
                return Json(UsersList, settings);
            }

    Tuesday, July 16, 2019 1:41 PM
  • User475983607 posted

    The variable UserName is assigned but all the others become null after a HttpPost.

    Correct, the View is designed to submit the Username only.  The View does not submit the UserDataModel or UserHistory properties therefore the model binder cannot populate these properties.  Please see the model binding link above for more information.

    You'll need to lookup the UserDataModel or UserHistory properties in the [HttpPost] Main() action or change the View design.  The main issue seems you think the model values should persist.  As you've experienced values do not automatically persist. It is up to you to write code to handle state.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, July 16, 2019 2:31 PM
  • User-1714333915 posted

    Harardin

    The variable UserName is assigned but all the others become null after a HttpPost.

    Correct, the View is designed to submit the Username only.  The View does not submit the UserDataModel or UserHistory properties therefore the model binder cannot populate these properties.  Please see the model binding link above for more information.

    You'll need to lookup the UserDataModel or UserHistory properties in the [HttpPost] Main() action or change the View design.  The main issue seems you think the model values should persist.  As you've experienced values do not automatically persist. It is up to you to write code to handle state.

    Thank you for explanation, right now i understand the logic.

    Tuesday, July 16, 2019 2:34 PM