0

I have an inventory application in a layout like this:

<body>
<div class="container" style="width: 100%">
        <div id="header"> blahblahblah </div>
        <div class="row">
            <div id="rendermenu" class="col-sm-2">
                @Html.Action("Menu", "Nav")
            </div>
            <div id="renderbody" class="col-sm-10">
                @RenderBody()
            </div>
    </div>
</div>

In the Home controller there is an action method that filters the repository sent to the view:

public ActionResult Index(string categoria, string marca)
{
    InventarioViewModel viewModel = new InventarioViewModel
    {
        Inventario = repository.GetInventario()
            .Where(i => (categoria == null || i.Item.Categoria == categoria)
                     && (marca == null || i.Item.Marca == marca))
            .OrderBy(i => i.Qta > 0)
            .ThenBy(i => i.Item.Categoria)
            .ThenBy(i => i.Item.Marca)
            .ThenBy(i => i.Item.Modello).ToList(),
        CategoriaCorrente = categoria,
        MarcaCorrente = marca
    };

    return View(viewModel);
}

It works fine, but only by typing the desired route in the browser. So I started writing a filter by putting a <select> element that presents the user the items categories, then binding an AJAX call to its change event. This is the markup for the menu view:

@using Magazzino.Domain.Infrastructure
@using Magazzino.Domain.Entities
@model List<Item>

@{ IEnumerable<Item> items = Model.DistinctBy(x => x.Categoria); }

<div class="text-center">Filtra per:</div>
<hr />
<div class="text-center">Categoria</div>
<select class="form-control lista-categorie" id="lista-categorie" data-action-url="@Url.Action("Index", "Home")" name="categoria">
    <option value>-- seleziona --</option>
    @foreach (Item item in items)
    {
        <option value="@item.Categoria">@item.Categoria</option>
    }
</select>

This is the AJAX call, put inside the usual $(document).ready(...):

$('#lista-categorie').on('change', function () {
    var e = $(this)[0];
    if (e.selectedIndex > 0) {
        var ajaxRequest = $.ajax({
            url: "/",
            type: "get",
            data: {
                categoria: e.options[e.selectedIndex].value,
                marca: null
            }
        })

        ajaxRequest.done(function (response) {
            $('#renderbody').html(response);
        });
    }
});

I also changed part of the controller where the view is rendered:

if (Request.IsAjaxRequest())
{
    return PartialView(viewModel);
}
else
{
    return View(viewModel);
}

but I get just an empty string. If try to get the full view, I see that the response has the whole page (layout and menu) BUT the Index view:

// previous markups from layout and menu
        <div id="renderbody" class="col-sm-10">




        </div>
    </div>
</div>

// other markups

I'm sure the Index action method is triggered because I put a breakpoint. Though, the moment I change the AJAX call itself this way, it works fine:

var ajaxRequest = $.ajax({
            url: "/" + e.options[e.selectedIndex].value,
            type: "get"
        })

but I don't really like this workaround, I'd like to have a more plain, efficient way of passing data to the controller.

How can I change this behaviour?

1
  • I think the problem is type:"get" try "post". Commented Mar 6, 2019 at 11:44

2 Answers 2

1

TOTALLY my bad: I re-edited the question because when I said "I'm sure the ViewModel get populated", it was true-ish. I only checked that the action method was triggered.

I have now checked the ViewModel and found the problem: I didn't take into account that the "null" value sent by the AJAX call isn't actually null, but an empty string. I have changed the LINQ expression accordingly and it works

InventarioViewModel viewModel = new InventarioViewModel
{
    Inventario = repository.GetInventario()
        .Where(i => (string.IsNullOrEmpty(categoria) || i.Item.Categoria == categoria) 
                 && (string.IsNullOrEmpty(marca) || i.Item.Marca == marca))
        .OrderBy(i => i.Qta > 0)
        .ThenBy(i => i.Item.Categoria)
        .ThenBy(i => i.Item.Marca)
        .ThenBy(i => i.Item.Modello).ToList(),
    CategoriaCorrente = categoria,
    MarcaCorrente = marca
};

Despite being a trivial bug (and an incredibly embarassing moment), I'd like to answer my own question and keep it for those who might face the same problem.

Cheers.

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

1 Comment

Kudos for honesty and self-answer
0
$('#lista-categorie').on('change',method_attached_to_event);

function method_attached_to_event(){

  var e = $(this)[0];
  if (e.selectedIndex > 0) {

    var url = '/';
    var obj = {};
    obj.categoria= e.options[e.selectedIndex].value;

    $.ajax({
      url:url,
      method:'POST',
      data:obj,
      success:success,
      error:error
    }); 

  }else{
    // Do something else
  }
}

function success(data,status,jqxhr){
   console.log(data);
}

function error( jqxhr, status, error ){
   console.log(status);
   console.log(error);
   console.log(jqxhr);
}

1 Comment

The problem was the null value I sent as one of the property value and how I thought it would've been handled by the controller: is not an actual null but an empty string. Thanks anyway...

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.