locked
Controller Action cannot recognize selected value from View RRS feed

  • Question

  • User1255309776 posted

    Hi,

    In my app, I have posts that shows budgets in different currencies. For that, I added select list of currencies for users to be able to filtre by currency.

    As I only have two currencies (and will be at most 3), I haven't created separate model for currency and would like to handle it from select tag option value or using SelectListItem.  Here is Associated models:

      public class Post
        {
            public int Id { get; set; }
            public string Title { get; set; }
            public string Description { get; set; }
            public string Currency { get; set; }
        }
    }

    ViewModel

     public class MenuViewModel
        {
            public int Id { get; set; }
            public Post Post { get; set; }
            public IEnumerable<Post> Posts { get; set; }
            public SelectListItem Mycurrency { get; set; } 
            public List<SelectListItem> Currencies { get; set; }
        }

    Action on Controller

      [HttpGet]
            public async Task<IActionResult> getCurrency(int Id, MenuViewModel menuModel)
            {
                menuModel.Category = await _samirDbContext.Categories.SingleOrDefaultAsync(c => c.Id == Id);
                menuModel.Subcategories = await _samirDbContext.Subcategories.Where(s => s.CategoryId == Id).ToListAsync();
                menuModel.Currencies = new List<SelectListItem>
                {
                    new SelectListItem {Text = "AZN", Value = "AZN"},
                    new SelectListItem {Text = "USD", Value = "USD"}
                };
    
                var selectedCurrency = menuModel.Currencies.Where(x => x.Selected).Select(y => y.Value).FirstOrDefault();
    
                menuModel.Posts = await _samirDbContext.Posts.Where(p => p.Subcategory.CategoryId == Id && p.Currency == selectedCurrency).OrderByDescending(p => p.Id).ToListAsync();    
                menuModel.Regions = await _samirDbContext.Regions.ToListAsync();
                return View("Categories", menuModel);
            } 

    View

    @model Samirad.Models.ViewModels.MenuViewModel
    <section class="searchfilter">
        <button class="backbtn" onclick="goBack()"><i class="fas fa-arrow-circle-left"></i></button>
        <p class="goback">Geri</p>
        <div class="container">
            <div class="filter-search">
                <div class="row">
                    <div class="col-lg-4 col-md-4 col-sm-6 col-12">
                        <div class="price-filter">
                            <h4>Minimum Qiymət</h4>
                            <input class="forprice" type="number" />
                            <button class="findall"><i class="fas fa-search"></i></button>
                        </div>
                    </div>
                    <div class="col-lg-2 col-md-2 col-sm-6 col-12">
                        <div class="currency-filter">
                            <h4>Valyuta</h4>
                            <select name="currencies" asp-for="Mycurrency.Selected" asp-items="@Model.Currencies" onchange="location.href='@Url.Action("getCurrency", "Home", new { Id = Model.Category.Id })'">
                                <option>Valyuta secin</option>
                            </select>
                        </div>
                    </div>
                   
    </section>
    <section class="posts container-fluid">
        <div class="post-container">
    
                            @foreach (Post item in Model.Posts)
                            {
                                if (item.Approved)
                                {
                                    if (n % 4 == 0)
                                    {
                        @:<div class="row">
                        }
                        <div class="col-lg-3 col-md-4 col-sm-6 col-12">
                            <div class="post">
                                <div class="heading">
                                    <h6>@item.Title</h6>
                                </div>
                                <div class="postcontent">
                                    <div class="row">
                                        <div class="col-lg-12 col-md-12">
                                            <!--
                                        <div class="imgframe">
                                            <img class="postimg" src="~/images/item.Image">
                                        </div>
                                           -->
                                            <div class="posttext">
                                                <p>
                                                    @item.Description
                                                </p>
                                                <p class="formore">
                                                    <a asp-action="getDetailed" asp-controller="Home" asp-route-id="@item.Id" target="_blank">ƏTRAFLI</a>
    
                                                </p>
                                            </div>
                                            <div class="dates">
                                                <p class="budget">Büdcə: <b>@item.MaxPrice</b> <b>@item.Currency</b></p>
    
                                                <p class="postdate">@item.CreatedDate.ToString("dd/MM/yyyy")</p>
    
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
    
                        if (n % 4 == 3)
                        {
                        @: </div>
                    }
    
                    n++;
    
                }
            }
    
        </div>
    </section>
    

    After debugging, I see that selectedCurrency gets null value thouhg one of the currencies were selected. Also, as you've seen from view, the action runs when selecting (on change) any currency, may it cause it to not recognize selected item? Note that I don't want to add button, so that after selecting, user would see his/her choice as a result of action.

    Please, advise.

    Tuesday, October 13, 2020 12:57 PM

All replies

  • User475983607 posted

    There are a lot of design problems in your code.  First, there's no code shown that calls getCurrency.  There's not even an HTML form.  getCurrency is defined as [HttpGet] which is possible but not standard.  [HttpPost] is typical.  The highlighted select does an HTTP Get to CatCurrency when the selection changes.  This causes a page refresh with unknown content.   There are issues with the view model design, HTML, pretty much everything. 

    You have to understand that providing assistance is practically impossible when the code has so many issues.

    Tuesday, October 13, 2020 2:19 PM
  • User1255309776 posted

    Dear mgebhard,

    The action getCurrency() actually was the same, I then changed that but forgot to the same for view, but the problem was not on that (it was working with its previous name, just wasn't getting Selected value, in that case it even wouldn't work). When it comes to get/post, here I do not post any value to database or do not implement any post operation. Here my aim is to just load the same view, but with posts with only selected currency. 

    Tuesday, October 13, 2020 2:43 PM
  • User475983607 posted

    The action getCurrency() actually was the same, I then changed that but forgot to the same for view, but the problem was not on that (it was working with its previous name, just wasn't getting Selected value, in that case it even wouldn't work). When it comes to get/post, here I do not post any value to database or do not implement any post operation. Here my aim is to just load the same view, but with posts with only selected currency. 

    Your design does not follow MVC or HTTP fundamentals.  The select onchange causes an Http Get.  The Http GET sends data in the URL.  Your design only sends the ID in the URL (route parameter).  The MenuViewModel is NOT part of the HTTP GET parameters.  Typically model data is sent in an Http POST. 

    I recommend setting time to go through a few beginning level tutorials.  You have to understand the fundamentals to design an MVC application.

    Tuesday, October 13, 2020 4:04 PM
  • User-1330468790 posted

    Hi FaridGN,

      

    First of all, I cannot take your codes to do a test since it is not a complete working demo to reproduce the problem.

    However, if you only care about the null value issue, the reason is pretty simple.

    Whenever you call this action, you will always reassign the view model "menuModel"'s property "Currencies" with a new list of type "List<SelectListItem>"

    menuModel.Currencies = new List<SelectListItem>
                {
                    new SelectListItem {Text = "AZN", Value = "AZN"},
                    new SelectListItem {Text = "USD", Value = "USD"}
                };

    Then you directly use linq to find out the one with selected = true but you never give it an initialization with a item containing a member "Selected" as true.

      

    Apart from that, you want to use HttpGet to pass the data to the action within below codes in View

    onchange="location.href='@Url.Action("getCurrency", "Home", new { Id = Model.Category.Id })'"

    However, as you can check it in the browser (Press F12 and expand checking element), the select element will be rendered with an "onchange" event handler => "location.href='/Home/getCurrency/XX". This will only pass an Id to the target action.

       

    To summarize, you might need to modify the design to use HttpGet action to get the view and use HttpPost action to transport data.

    Reference: https://stackoverflow.com/a/16126426/12871232

    Otherwise, you could use ajax call function when the user change the selected element from the select list and get view without page refresh.

    Reference: https://stackoverflow.com/a/39523863/12871232

     

    Best regards,

    Sean

    Wednesday, October 14, 2020 7:17 AM