0

Hello guys I have some MVC application and I try to get values from my dropdown list container. I've tried to get things that is recomended on this way How to get DropDownList SelectedValue in Controller in MVC but it work in some cases but it dont in others.

On my view I have two drop down list containers and two buttons for choosing and removing from one list to another(javascript offcourse).

When I have 3 Authors in container ChoosenAuthos and I remove just one from them, in my controller in if statement I get that Request.Form["ChoosenAuthors"] is null, and he has two Authors left in container.

My View:

@model PrivateLibrary.Models.Book

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>
<script src='https://code.jquery.com/jquery-3.1.0.min.js'></script>
<script type="text/javascript" src="~/Scripts/CreateBook.js"></script>


@using (Html.BeginForm())
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.Book_Id)

    <div class="form-group">
        @Html.LabelFor(model => model.Book_Name, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Book_Name, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Book_Name, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.ISBN_Number, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ISBN_Number, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ISBN_Number, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Book_Desription, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Book_Desription, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Book_Desription, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.User_Id, "User_Id", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownList("User_Id", null, htmlAttributes: new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.User_Id, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        <div class="container">
            <div class="row">
                <div class="col-sm-2">
                    <b>Authors: </b>
                    @Html.DropDownList("Authors", new SelectList(ViewBag.Authors, "Value", "Text"), htmlAttributes: new { size = "10", @class = "form-control", Multiple = "multiple", style = "width:150px;height : 200px" })
                </div>
                <div class="col-sm-2 btn-group-vertical">
                    <br><br><br>
                    <button type="button" class="btn btn-primary btn-md" id="choose">Choose</button>
                    <button type="button" class="btn btn-primary btn-md" id="remove">Remove</button>
                </div>
                <div class="col-sm-2">
                    <b>Choosen Authors:</b><br>
                    @Html.DropDownList("ChoosenAuthors", new SelectList(ViewBag.ChoosenAuthors, "Value", "Text"), htmlAttributes: new { size = "10", @class = "form-control", Multiple = "multiple", style = "width:150px;height : 200px" })
                </div>
            </div>
        </div>
    </div>


    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

My javascript running on that page:

$(function () {
$('#choose').click(function () {
    inHTML = "";
    $("#Authors option:selected").each(function () {
        inHTML += '<option value="' + $(this).val() + '">' + $(this).text() + '</option>';
    });
    $("#Authors option:selected").remove();
    $("#ChoosenAuthors").append(inHTML);
});

$('#remove').click(function () {
    inHTML = "";
    $("#ChoosenAuthors option:selected").each(function () {
        inHTML += '<option value="' + $(this).val() + '">' + $(this).text() + '</option>';
    });
    $("#ChoosenAuthors option:selected").remove();
    $("#Authors").append(inHTML);
});

$("form").submit(function (e) {
    $("#ChoosenAuthors option").attr("selected", "selected");
});

});

My controller:

private bool ContainsAuthor(int authorId, List<BookAuthor> authors)
    {
        foreach (BookAuthor bookAuthor in authors)
        {
            if(bookAuthor.Author_Id == authorId)
            {
                return true;
            }
        }
        return false;
    }

    private void FillChoosenAuthors(BookCorrect book)
    {
        List<SelectListItem> choosen = new List<SelectListItem>();
        List<SelectListItem> authors = new List<SelectListItem>();
        List<Author> allAuthors = db.Author.ToList();
        List<BookAuthor> authorsFromBook = book.BookAuthor.ToList();
        if (authorsFromBook.Any())
        {
            foreach (BookAuthor choosenAuthor in authorsFromBook)
            {
                choosen.Add(new SelectListItem { Text = choosenAuthor.Author.Author_Name, Value = choosenAuthor.Author.Author_Name });

            }
            foreach (Author author in allAuthors)
            {
                if (!ContainsAuthor(author.Author_Id, authorsFromBook))
                {
                    authors.Add(new SelectListItem { Text = author.Author_Name, Value = author.Author_Name });
                }
            }
        }
        else
        {
            foreach (Author author in allAuthors)
            {
                authors.Add(new SelectListItem { Text = author.Author_Name, Value = author.Author_Name });
            }
        }
        ViewBag.Authors = authors;
        ViewBag.ChoosenAuthors = choosen;
    }


 [Filters.AdminBookAuthorization]
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        BookCorrect bookCorrect = db.BookCorrect.Find(id);
        if (bookCorrect == null)
        {
            return HttpNotFound();
        }
        FillChoosenAuthors(bookCorrect);
        return View(bookCorrect);
    }

    // POST: BookCorrects/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "Book_Id,Book_Name,ISBN_Number,Book_Desription,User_Id")] BookCorrect bookCorrect)
    {
        if (ModelState.IsValid)
        {
            if (bookCorrect.ISBN_Number.All(Char.IsLetter))
            {
                ModelState.AddModelError("", "ISBN is not valid. No letters in ISBN number");
                return View(bookCorrect);
            }
            db.Entry(bookCorrect).State = EntityState.Modified;

            if (Request.Form["ChoosenAuthors"] != null)
            {
                string choosenAuthors = Request.Form["ChoosenAuthors"].ToString();
                string[] authorsNames = choosenAuthors.Split(',');
                List<BookAuthor> authorsNew = new List<BookAuthor>();

                foreach (var item in db.Author)
                {
                    BookAuthor bookAuthor = new BookAuthor();
                    for (int i = 0; i < authorsNames.Length; i++)
                    {
                        if (authorsNames[i].Equals(item.Author_Name))
                        {
                            bookAuthor.Author = item;
                            bookAuthor.Author_Id = item.Author_Id;
                            bookAuthor.BookCorrect = bookCorrect;
                            bookAuthor.BookAuthor_Id = bookCorrect.Book_Id;
                            authorsNew.Add(bookAuthor);
                        }
                    }
                }
                foreach (BookAuthor bookAuthor in db.BookAuthor)
                { 
                    if(bookAuthor.Book_Id == bookCorrect.Book_Id)
                    {
                        bookCorrect.BookAuthor.Remove(bookAuthor);
                        db.BookAuthor.Remove(bookAuthor);
                    }
                }

                db.SaveChanges();
                foreach (BookAuthor choosen in authorsNew)
                {
                    db.BookAuthor.Add(choosen);
                    bookCorrect.BookAuthor.Add(choosen);
                }
            }else
            {
                foreach (BookAuthor bookAuthor in db.BookAuthor)
                {
                    if (bookAuthor.Book_Id == bookCorrect.Book_Id)
                    {
                        bookCorrect.BookAuthor.Remove(bookAuthor);
                        db.BookAuthor.Remove(bookAuthor);
                    }
                }
            }
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.User_Id = new SelectList(db.LibraryUser, "User_Id", "Username", bookCorrect.User_Id);
        return View(bookCorrect);
    }
radem359
  • 1
  • 2
  • 1
    You're doing it wrong. Hint: If you find yourself using `Request.Form` when doing MVC, you're doing it wrong. You should be using model binding. You should also be using the lambda forms (ending in For) of all HTML helpers (including DrowDownListFor) – Erik Funkenbusch Oct 08 '18 at 15:50
  • Also, see https://stackoverflow.com/questions/12700943/mvc-viewmodel-error-no-parameterless-constructor-defined-for-this-object/12701768#12701768 - The symptoms are not the same, but at least one of your problems is related to naming your DropDownList the same as your SelectListItems – Erik Funkenbusch Oct 08 '18 at 19:41
  • Hello. Thank you. I understand that you are teaching me what is rigth way. But yesterday I tried with some ModelView and naming that but that doesnt change mager problem. And that is when I select author and click remove that list is null. And even if I click chose latter and name get to that container it is still null – radem359 Oct 09 '18 at 23:35

0 Answers0