3

In the following code of an ASP.NET MVC Core project, the Get action method Test(...) is displaying a dropdown list of years. By default, the dropdown displays the first year in the list (i.e. 2000) as a Selected value. If I want to display a particular year in the same list as a selected value, how can I achieve it from action method Test(...) without using ViewModel techinque? A solution for either a select tag helper or a DropdownList html helper will be fine - but Selected value has to set from action method.

In short, how would you set a particular year as a Selected Value in this list: ViewBag.YearsList = Enumerable.Range(2000, 15).Select(g => new SelectListItem { Value = g.ToString(), Text = g.ToString() }).ToList();

Models:

    public class BloggingContext : DbContext
    {
        public BloggingContext(DbContextOptions<BloggingContext> options)
            : base(options)
        { }

        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }

        public IList<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public int PostYear { get; set; }
        public int BlogId { get; set; }
        public Blog Blog { get; set; }
}

Controller: Only relevant action methods are shown.

 public class BlogsController : Controller
{
    private readonly BloggingContext _context;

    public BlogsController(BloggingContext context)
    {
        _context = context;    
    }

    // GET: Blogs
    public async Task<IActionResult> Index()
    {
        return View(_context.Blogs.ToList());
    }

    // GET: /Blogs/Test
    [HttpGet]
    public async Task<IActionResult> Test(string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        ViewBag.YearsList = Enumerable.Range(2000, 15).Select(g => new SelectListItem { Value = g.ToString(), Text = g.ToString() }).ToList();

        //return View(await _context.Blogs.Include(p => p.Posts).ToListAsync());
        var qrVM = from b in _context.Blogs
                    join p in _context.Posts on b.BlogId equals p.BlogId into bp
                    from c in bp.DefaultIfEmpty()
                    select new BlogsWithRelatedPostsViewModel { BlogID = b.BlogId, PostID = (c == null ? 0 : c.PostId), Url = b.Url, Title = (c == null ? string.Empty : c.Title), Content = (c == null ? string.Empty : c.Content) };

        return View(await qrVM.ToListAsync());
    }

    // POST: /Blogs/Test
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Test(IList<BlogsWithRelatedPostsViewModel> model, string GO, int currentlySelectedIndex, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        ViewBag.YearsList = Enumerable.Range(2000, 15).Select(g => new SelectListItem { Value = g.ToString(), Text = g.ToString() }).ToList();

        if (!string.IsNullOrEmpty(GO))
        {
            var qrVM = from b in _context.Blogs
                        join p in _context.Posts on b.BlogId equals p.BlogId into bp
                        from c in bp.DefaultIfEmpty()
                        where c == null? true : c.PostYear.Equals(currentlySelectedIndex)
                        select new BlogsWithRelatedPostsViewModel { BlogID = b.BlogId, PostID = (c == null ? 0 : c.PostId), Url = b.Url, Title = (c == null ? string.Empty : c.Title), Content = (c == null ? string.Empty : c.Content) };
            return View(await qrVM.ToListAsync());
        }
        else if (ModelState.IsValid)
        {
            foreach (var item in model)
            {
                var oPost = _context.Posts.Where(r => r.PostId.Equals(item.PostID)).FirstOrDefault();
                if (oPost != null)
                {
                    oPost.Title = item.Title;
                    oPost.Content = item.Content;
                    oPost.PostYear = currentlySelectedIndex;
                    oPost.BlogId = item.BlogID; //according to new post below the blogId should exist for a newly created port - but just in case
                }
                else
                {
                    if (item.PostID == 0)
                    {
                        Post oPostNew = new Post { BlogId = item.BlogID, Title = item.Title, Content = item.Content, PostYear = currentlySelectedIndex }; //need to use currentlySelectedIndex intead of item.FiscalYear in case of adding a record
                        _context.Add(oPostNew);
                    }

                }
            }
            await _context.SaveChangesAsync();
            //return RedirectToLocal(returnUrl);
            return View(model);
        }

        // If we got this far, something failed, redisplay form
        return View();
    }
 }

Test.cshtml View

@model IList<ASP_Core_Blogs.Models.BlogPostViewModels.BlogsWithRelatedPostsViewModel>

<div class="row">
    <div class="col-md-12">
        <form asp-controller="Blogs" asp-action="Test" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
            @{
                IEnumerable<SelectListItem> yearsList = (IEnumerable<SelectListItem>)ViewBag.YearsList;
                var currentlySelectedIndex = 0; // Currently selected index (usually will come from model)
            }
            <strong>Select a Post Year</strong>
            <h6>Choose a year and a URL to begin:</h6>
            <label>Year:</label><select asp-for="@currentlySelectedIndex" asp-items="yearsList"></select><input type="submit" class="btn btn-default" name="GO" value="GO" />
            <table class="table">
                <thead>
                    <tr>
                        <th></th>
                        <th></th>
                        <th>Url</th>
                        <th>Title</th>
                        <th>Content</th>
                    </tr>
                </thead>
                <tbody>
                    @for (int i=0; i< Model.Count(); i++)
                    {
                        <tr>
                            <td>@Html.HiddenFor(r => r[i].BlogID)</td>
                            <td>@Html.HiddenFor(r => r[i].PostID)</td>
                            <td>
                                @Html.TextBoxFor(r => r[i].Url)
                            </td>
                            <td>
                                @Html.TextBoxFor(r => r[i].Title)
                            </td>
                            <td>
                                @Html.TextBoxFor(r => r[i].Content)
                            </td>
                        </tr>
                    }
                </tbody>
            </table>
            <button type="submit" class="btn btn-default">Save</button>
        </form>
    </div>
</div>

3 Answers 3

2

Since you want to avoid using a view model, you can't use DropDownListFor but you can use DropDownList

    @Html.DropDownList("fieldname", new SelectList(ViewBag.YearsList, ViewBag.SelectedYear))
Sign up to request clarification or add additional context in comments.

Comments

2

You can set the selected value in the action method as follows:

ViewBag.YearsList = Enumerable.Range(2000, 15)
    .Select(g => new SelectListItem 
    { 
        Value = g.ToString(),
        Text = g.ToString(),
        Selected = (g == currentlySelectedIndex)
    }).ToList();

This only works if you are not binding to a model:

<select name="selectedYear" asp-items="yearsList"></select>

Comments

0

You can solve this declaring list and set Selected value for one specific item, you can get the item an any way you want (linq, index, etc).

Sample code:

var list = Enumerable.Range(2000, 15).Select(g => new SelectListItem { Value = g.ToString(), Text = g.ToString() }).ToList();

// Select the item using index reference, this line selects '2010' item
list[10].Selected = true;

ViewBag.YearsList = list;

2 Comments

Using your suggestion the ViewBag.YearsList did not change the selected value when I clicked on the GO button on my View. For example, for a test I selected the year to be 2005 from the dropdown and clicked on the Go button when the model sent by the view was posted it still displayed 2005 as selected value and not 2010 that was set in the POST action method Test(...)
You can send selected year via url parameter y return value via ViewBag

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.