1

Using ASP.NET Core 2.2

I'm trying to bind a complex object from JQuery to pass it to controller. An invoice view contains selected products' Id and its quantity which I need to bind to the model property which is a list of object SelectedProds.

onclick of submit button I'm setting the value of hidden field with the dictionary object of the selected products' id and its quantity.

Razor View


  <form asp-action="AddNewInvoice">

        <div class="card-body">
            <div class="row">
                <div class="col-md-12">
                    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                    <div class="form-group row">
                        <div class="col-md-3">
                            <label asp-for="CompanyId" class="control-label"></label>
                            <select asp-for="CompanyId" class="form-control" asp-items="@Model.CompanyIdList"></select>
                        </div>
                        <div class="col-md-3">
                            <label asp-for="InvoiceDate" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-calendar"></i>
                                    </span>
                                </div>
                                <input type="date" asp-for="InvoiceDate" class="form-control" />
                            </div>
                            <span asp-validation-for="InvoiceDate" class="text-danger"></span>
                        </div>
                        <div class="col-md-3">
                            <label asp-for="BuyersOrderNo" class="control-label"></label>
                            <input asp-for="BuyersOrderNo" class="form-control" />
                            <span asp-validation-for="BuyersOrderNo" class="text-danger"></span>
                        </div>
                        <div class="col-md-3">
                            <label asp-for="BuyersOrderDate" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-calendar"></i>
                                    </span>
                                </div>
                                <input type="date" asp-for="BuyersOrderDate" class="form-control" />
                            </div>
                            <span asp-validation-for="BuyersOrderDate" class="text-danger"></span>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-md-12">
                            <label asp-for="SelectedProducts" class="control-label"></label>
                            <select asp-for="SelectedProducts" asp-items="@Model.ProductList" class="form-control select2"></select>
                            <span asp-validation-for="SelectedProducts" class="text-danger"></span>
                           <input type="hidden" asp-for="SelectedProds" />
                        </div>
                    </div>
                    <hr />
                    <div class="form-group">
                        <div class="col-md-12" id="Items">
                            <div class="brand-card-body row text-lg-center text-uppercase">
                                <div class="col-md-2">Product Code</div>
                                <div class="col-md-5">Description</div>
                                <div class="col-md-2">Capacity in ml </div>
                                <div class="col-md-1"> Price </div>
                                <div class="col-md-1">Quantity</div>
                            </div>
                            <div class="row"></div>

                        </div>
                    </div>
                    <hr />
                    <div class="form-group row col-12">
                        <div class="col-md-3">
                            <label asp-for="TotalAmount" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-rupee"></i>
                                    </span>
                                </div>
                                <input asp-for="TotalAmount" readonly="readonly" class="form-control" />
                            </div>
                            <span asp-validation-for="TotalAmount" class="text-danger"></span>
                        </div>
                        <div class="col-md-2">
                            <label asp-for="LessDiscount" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-percent"></i>
                                    </span>
                                </div>
                                <input asp-for="LessDiscount" type="number" min="0" placeholder="Percentage" class="form-control">
                            </div>
                            <span asp-validation-for="LessDiscount" class="text-danger"></span>
                        </div>
                        <div class="col-md-2">
                            <label asp-for="DiscountedAmount" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-rupee"></i>
                                    </span>
                                </div>
                                <input asp-for="DiscountedAmount" readonly="readonly" class="form-control" />
                            </div>
                            <span asp-validation-for="DiscountedAmount" class="text-danger"></span>
                        </div>
                        <div class="col-md-2">
                            <label asp-for="TaxableValue" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-rupee"></i>
                                    </span>
                                </div>
                                <input asp-for="TaxableValue" type="number" min="0" readonly="readonly" class="form-control" />
                            </div>
                            <span asp-validation-for="TaxableValue" class="text-danger"></span>
                        </div>
                        <div class="col-md-3">
                            <label asp-for="TotalTaxAmount" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-rupee"></i>
                                    </span>
                                </div>
                                <input asp-for="TotalTaxAmount" readonly="readonly" class="form-control" />
                            </div>
                            <span asp-validation-for="TotalTaxAmount" class="text-danger"></span>
                        </div>
                    </div>
                    <div class="form-group row col-12">

                        <div class="col-md-3">
                            <label asp-for="NetPayable" class="control-label"></label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text">
                                        <i class="fa fa-rupee"></i>
                                    </span>
                                </div>
                                <input asp-for="NetPayable" type="number" min="0" readonly="readonly" class="form-control" />
                            </div>
                            <span asp-validation-for="NetPayable" class="text-danger"></span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="card-footer">
            <button type="submit" class="btn btn-primary" onclick="bindList()">
                <i class="fa fa-dot-circle-o"></i> Create Invoice
            </button>
            <button type="reset" class="btn btn-danger">
                <i class="fa fa-ban"></i> Reset
            </button>
        </div>
    </form>

<script>
var itemsArray = [];

 $(document).on("keyup change", ".qtyy", function () {

            var sum = 0;

            $(".qtyy").each(function () {
                var id=  // getting id of the product
                var qty = //getting quantity;

                obj = {};
                obj.Code = id;
                obj.Quantity = qty;

                itemsArray.push(obj);
            });

//calling below function on onclick of submit
  function bindList() {

        $('#SelectedProds').val(JSON.stringify(itemsArray));
        }
</script>

Controller Action

 [HttpPost]
        public IActionResult AddNewInvoice(CreateInvoiceViewModel model)
        { . . . 

ViewModel

public class CreateInvoiceViewModel
    {
        [Required]
        [DisplayName("Select Company")]
        public string CompanyId { get; set; }

        public List<SelectListItem> CompanyIdList { get; set; }

        public List<SelectListItem> ProductList { get; set; }

        [DisplayName("Select Products")]
        public Dictionary<string, string> SelectedProducts { get; set; }

        public List<ProdQuantity> SelectedProds { get; set; }
        [Required]
        [DisplayName("Invoice Date")]
        public DateTime InvoiceDate { get; set; } = DateTime.Today.Date;

        [Required]
        [DisplayName("Buyer's Order #")]
        public string BuyersOrderNo { get; set; }

        [Required]
        [DisplayName("Buyer's Order Date")]
        public DateTime BuyersOrderDate { get; set; } = DateTime.Today.Date;

        public string Notes { get; set; }

        [Required]
        [DisplayName("Total Amount")]
        public string TotalAmount { get; set; }

        [DisplayName("Amount In Words")]
        public string AmountInWords { get; set; }

        [Required]
        [DisplayName("Discount Percentage")]
        public string LessDiscount { get; set; }

        [Required]
        [DisplayName("Discounted Amount")]
        public string DiscountedAmount { get; set; }

        [DisplayName("Net Payable")]
        public string NetPayable { get; set; }

        [DisplayName("Hsn Code")]
        public string HsnCode { get; set; }

        [Required]
        [DisplayName("Taxable Amount")]
        public string TaxableValue { get; set; }

        [DisplayName("Central Tax Rate")]
        public string CentralTaxRate { get; set; }

        [DisplayName("State Tax Rate")]
        public string StateTaxRate { get; set; }

        [Required]
        [DisplayName("Total Tax Amount")]
        public string TotalTaxAmount { get; set; }
    }

    public class ProdQuantity
    {
        public string Code { get; set; }
        public string Quantity { get; set; }
    }

The SeletectedProds list is coming as empty in Action.

Help will be appreciated.

3
  • First you should check what you send using your browser's debug console > network tab. I guess SelectedProds does not look like something you can convert to List of ProdQuantity. Commented Jun 30, 2019 at 16:23
  • I think if you make SelectedProducts a List<SelectListItem>, this would work? You're not passing a dictionary, but an array. Commented Jun 30, 2019 at 17:17
  • @christoph I checked. Correctly setting the Hidden field value. Commented Jul 1, 2019 at 5:46

1 Answer 1

1

The first thing is that i don't find where is your .qtyy element , so i just create test value like :

@section Scripts{ 
    <script>
        var itemsArray = [];
        $(function () {

            var id = "1"
            var qty = "2"

            obj = {};
            obj.Code = id;
            obj.Quantity = qty;

            itemsArray.push(obj);

        })

        function bindList() {

            $('#SelectedProds').val(JSON.stringify(itemsArray));
        }

    </script>

}

You can create a custom model binder for your SelectedProds property :

public class CustomModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        var value = valueProviderResult.FirstValue; // get the value as string
        var result= JsonConvert.DeserializeObject<List<ProdQuantity>>(value);    
        bindingContext.Result = ModelBindingResult.Success(result);
        return Task.CompletedTask;
    }
}

Then bind to your property :

[BindProperty(BinderType = typeof(CustomModelBinder))]
public List<ProdQuantity> SelectedProds { get; set; }

result :

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

I have a JavaScript function which adds a dynamic row on select of dropdown. The qtyy class is added to the quantity textbox that is generated dynamically.. Anyways why the custom model binder is required? Asp.net mvc didn't require such model binder implementation to bind complex objects.
@BlushMaq , ok ,then try with my code and check whether it works
Yes.. I'll try it tonight. Thanks in advance.
Easiest description of creating a model binder I've seen - but to bind to a list, I found I had to loop through the Values property and add each to a list type to return.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.