0

I'm coding with ASP.NET Core. I have a form in a view that has several select inputs to insert orders. I want to change asp-items in select input of Products at run time, after changing select inputs of Properties of Products. In other words, a select input populates with a new list, after selecting new value in other inputs.

I try to use ajax for bind new list to select. but I don't know why ajax can't send input data to controller.

View's Code:

            <form id="InsertForm">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                        <div class="form-group">
                            <label asp-for="ProductTitleId" class="control-label"></label>
                            <select asp-for="ProductTitleId" asp-items="@ViewBag.ProductTitles" class="form-control" id="txtProductTitleId" name="SearchItem">
                                <option value="0" disabled selected>Select an item...</option>
                            </select>
                            <span asp-validation-for="ProductTitleId" class="text-danger </span>
                        </div>
                        <div class="form-group">
                            <label asp-for="ProductTypeId" class="control-label"></label>
                            <select asp-for="ProductTypeId" asp-items="@ViewBag.ProductTypes" class="form-control" id="txtProductTypeId" name="SearchItem">
                                <option value="0" disabled selected>Select an item...</option>
                            </select>
                            <span asp-validation-for="ProductTypeId" class="text-danger"></span>
                        </div>
                        <div class="form-group">
                            <label asp-for="SizeId" class="control-label"></label>
                            <select asp-for="SizeId" asp-items="@ViewBag.Sizes" id="txtSizeId" class="form-control" name="SearchItem">
                                <option value="0" disabled selected>Select an item...</option>
                            </select>
                            <span asp-validation-for="SizeId" class="text-danger"></span>
                        </div>                
                        <div class="form-group">
                            <label asp-for="FinalProductId" class="control-label"></label>
                            <select asp-for="FinalProductId" asp-items="@ViewBag.FinalProducts" class="form-control" dir="rtl" id="txtFinalProductId">
                                <option value="0" disabled selected>Select an item...</option>
                            </select>
                            <span asp-validation-for="FinalProductId" class="text-danger"></span>
                        </div>
                <div class="form-group">
                            <button type="submit" class="btn">Insert</button>
                </div>
            </form>
    
    <script>
        $(document).ready(function () {
            $('[name = SearchItem]').change(function () {
                var _url = '@Url.Action("FindFinalProductCode", "Order")';
                $.ajax({
                    url: _url,
                    type: "Post",
                    data: {
                        ProductTitleId: $("#txtProductTitleId option:selected").val(),
                        ProductTypeId: $("#txtProductTypeId option:selected").val(),
                        SizeId: $("#txtSizeId option:selected").val(),
                    },
                    dataType: "json",
                    contentType: "application/json;charset=utf-8",
                    success: function (data) {
                        $("#txtFinalProductId").empty();
                        $("#txtFinalProductId").append('<option value="' + "0" + '">' + "Select an item..." + '</option>');
                        $.each(data, function (i, item) {
                            $("#txtFinalProductId").append('<option value="' + item.Id + '">' + item.FinalProductCode + '</option>');
                            alert(i + ": " + item.Id);
                        });
                    },
                    error: function (data) {
                        alert(data);
                    }
                });
    
            });
        });
    
    </script>

Controller's Code: OrderController.cs

[HttpPost]
public IActionResult FindFinalProductCode(FinalProductViewModel finalProductViewModel)
{
    List<FinalProduct> finalProducts = FindFinalProduct(finalProductViewModel);
    return Json(finalProducts);
}

ViewModel's Code: FinalProductViewModel.cs

    public class FinalProductViewModel
    {
        [Display(Name = "Title")]
        public int ProductTitleId { get; set; }
    
        [Display(Name = "Type")]
        public int ProductTypeId { get; set; }
    
        [Display(Name = "Size")]
        public int SizeId { get; set; }
    }

At run time, finalProductViewModel is empty when is posted to the action.

I changed ajax code like this (remove datatype and content type):

<script>
    $(document).ready(function () {
        $('[name = SearchItem]').change(function () {
            var _url = '@Url.Action("FindFinalProductCode", "Order")';
            $.ajax({
                url: _url,
                type: "Post",
                data: {
                    ProductTitleId: $("#txtProductTitleId option:selected").val(),
                    ProductTypeId: $("#txtProductTypeId option:selected").val(),
                    SizeId: $("#txtSizeId option:selected").val(),
                },
                success: function (data) {
                    $("#txtFinalProductId").empty();
                    $("#txtFinalProductId").append('<option value="' + "0" + '">' + "Select an item..." + '</option>');
                    $.each(data, function (i, item) {
                        $("#txtFinalProductId").append('<option value="' + item.Id + '">' + item.FinalProductCode + '</option>');
                        alert(i + ": " + item.Id);
                    });
                },
                error: function (data) {
                    alert(data);
                }
            });

        });
    });

</script>

The controller is changed like this:

[HttpPost]
public IActionResult FindFinalProductCode(FinalProductViewModel finalProductViewModel)
{
    List<FinalProduct> finalProducts = FindFinalProduct(finalProductViewModel);
    return ok(finalProducts);
}

but this time ajax has error when action returns data.

How to change my code to run correctly?

Question: What are another ways of sending a list from action controller to view(to re-populate asp-items of select input)??

NedaM
  • 87
  • 3
  • 10

1 Answers1

1

After the server return the json result to the client, the response's item's property will change from "FinalProductCode " to "finalProductCode ", "Id" to "id".

So I suggest you could modify the script to the $("#txtFinalProductId").append('<option value="' + item.id + '">' + item.finalProductCode + '</option>');, then it will work well.

Details scripts:

    <script>
    $(document).ready(function () {
        $('[name = SearchItem]').change(function () {
            var _url = '@Url.Action("FindFinalProductCode", "Home")';
            $.ajax({
                url: _url,
                type: "Post",
                data: {
                    ProductTitleId: $("#txtProductTitleId option:selected").val(),
                    ProductTypeId: $("#txtProductTypeId option:selected").val(),
                    SizeId: $("#txtSizeId option:selected").val(),
                },
                dataType: "json",
                contentType: "application/json;charset=utf-8",
                success: function (data) {
                    $("#txtFinalProductId").empty();
                    $("#txtFinalProductId").append('<option value="' + "0" + '">' + "Select an item..." + '</option>');
                    $.each(data, function (i, item) {
                        $("#txtFinalProductId").append('<option value="' + item.id + '">' + item.finalProductCode + '</option>');
                        alert(i + ": " + item.id);
                    });
                },
                error: function (data) {
                    alert(data);
                }
            });

        });
    });

</script>

Result:

enter image description here


Controller:

    [HttpPost]
    public IActionResult FindFinalProductCode([FromBody]FinalProductViewModel finalProductViewModel)

Scripts:

    <script>
    $(document).ready(function () {
        $('[name = SearchItem]').change(function () {
            var _url = '@Url.Action("FindFinalProductCode", "Home")';
            var finalProductViewModel = {};
            finalProductViewModel.ProductTitleId = $("#txtProductTitleId option:selected").val();
            finalProductViewModel.ProductTypeId = $("#txtProductTypeId option:selected").val();
            finalProductViewModel.SizeId = $("#txtSizeId option:selected").val()

             $.ajax({
                url: _url,
                type: "Post",
                data: JSON.stringify(finalProductViewModel) ,
                dataType: "json",
                contentType: "application/json;charset=utf-8",
                success: function (data) {
                    $("#txtFinalProductId").empty();
                    $("#txtFinalProductId").append('<option value="' + "0" + '">' + "Select an item..." + '</option>');
                    $.each(data, function (i, item) {
                        $("#txtFinalProductId").append('<option value="' + item.id + '">' + item.finalProductCode + '</option>');
                        alert(i + ": " + item.id);
                    });
                },
                error: function (data) {
                    alert(data);
                }
            });

        });
    });

</script>
Brando Zhang
  • 22,586
  • 6
  • 37
  • 65
  • Thanks for your answer, but in this code ajax send no data to controller. in other words finalProductViewModel is empty in action. – NedaM Nov 02 '22 at 03:59
  • 1
    Please check my update answrer ,you should firslty modify the jquery's data format and then modify the controller action to add [Frombody]. – Brando Zhang Nov 02 '22 at 05:26
  • Thanks again. But finalProductViewModel in input of action is null yet. Do I need to add any special library?! I don't understand why this doesn't work... – NedaM Nov 02 '22 at 06:54
  • Note: I Added (System.Text.Json;) and (System.Text.Json.Serialization;) Before. – NedaM Nov 02 '22 at 07:00
  • 1
    Please put a breadpoint at backend to see if the data has sent to the controller method. – Brando Zhang Nov 02 '22 at 08:12
  • I did this, and saw the finalProductviewmodel was null in action while in ajax method (using console.log) finalProductviewModel has correct data. – NedaM Nov 02 '22 at 08:44