How to get the selected item from a DropDownList? - c#

I know this is a question that many people responded on the site , but no solution seems to work to my problem.
I am new to MVC and do not know how to send the selected item in the drop down list to the controller .
public class MonthDropDownList
{
public IEnumerable<SelectListItem> Months
{
get
{
return DateTimeFormatInfo
.InvariantInfo
.MonthNames
.Where(m => !String.IsNullOrEmpty(m) )
.Select((monthName, index) => new SelectListItem
{
Value = (index + 1).ToString(),
Text = monthName
});
}
}
public int SelectedMonth { get; set; }
}
Here is my view :
#model Plotting.Models.MonthDropDownList
#Html.DropDownListFor(x => x.SelectedMonth, Model.Months)
#using (Html.BeginForm("MonthlyReports", "Greenhouse", FormMethod.Post))
{
<input type="submit" name="btnSubmit" value="Monthly Report" />
}
And here is the ActionResult in which i should use the selected date :
public ActionResult MonthlyReports(MonthDropDownList Month)
{
Debug.Write("Month" + Month.SelectedMonth);// <- always = 0
InitChartModel();
cDate.DateTitle = "Day";
string msg = dal.Connection("month");
List<Greenhouse> greenhouse = dal.FindIfDMY("month" , Month.SelectedMonth , msg);
cDate.DateData = GetChart(greenhouse, "month");
return View("MonthlyReports", cDate);
}

You should move your DropDownList into your form.
#model Plotting.Models.MonthDropDownList
#using (Html.BeginForm("MonthlyReports", "Greenhouse", FormMethod.Post))
{
#Html.DropDownListFor(x => x.SelectedMonth, Model.Months)
<input type="submit" name="btnSubmit" value="Monthly Report" />
}

Your form control needs to be inside the form tags
#using (Html.BeginForm("MonthlyReports", "Greenhouse", FormMethod.Post))
{
#Html.DropDownListFor(x => x.SelectedMonth, Model.Months) // move here
<input type="submit" name="btnSubmit" value="Monthly Report" />
}

Related

Passing list of dynamically created dropdownlists to controller in MVC

I have a MVC5 project with a form where the user can click and add new dropdowns dynamically, it uses select2 and ajax to get the posible values and filter...
//ViewModel
public class MyViewModel
{
public List<string> Skus { get; set; }
//Tried public List<List<string>> Skus { get; set; } w/no success
}
//MVC Razor view
<div id="SkuContainer">
Product variations: #Html.DropDownListFor(m => m.Skus, Enumerable.Empty<SelectListItem>(), "Select", new { multiple = "true", #class = "Skus", #id = "Skus1" })
</div>
<input id="btnAddSku" type="button" value="Add variations" class="btn btn-primary" />
<input id="btnRemoveSku" type="button" value="Remove variations" class="btn btn-danger" />
....
$(document).ready(function () {....
$("#btnAddSku").on("click", function () {
var i = 2;
var dropdown = "<select data-val='true' class='Skus' id=Skus" + i + " name=Skus style='width:1000px' multiple> </select >";
var VariationContainer = "<div id='variationsdiv'><br/> Product variations: " + dropdown + " </div>";
$("#SkuContainer").append(VariationContainer);
i++;
});
...
//Controller:
public ActionResult Confirm(MyViewModel model)
{
Debug.WriteLine(model.Skus ) // I get all the selected values, it works but I can't diferenciate each dropdown because of how the model is structured.
}
How can I set the model and the view to get a list of lists of selected values so I can diferentiate each dropdown?
Thank you

Multi select drop-down items auto select attribute on update

On a page i have a multi select drop-down menu. It works fine whenever i need to insert data BUT a problem accrues when i need to update the inserted data.
The Problem Whenever i click the edit button next to my data (in my case - about book data) every field inside the Form fills up but the select drop-down menu items does not get auto selected to what was previously selected. I have to re-select it manually again. The process of updating the data itself works fine (once i re-select it again).
It uses many-to-many relationship. Worked fine when i used check-boxes but I want to re-do it on drop-down menu.
The Controller
public ViewResult Index(int? Id)
{
SelectList selectList = new SelectList(_authorRepository.GetAllAuthors()
.Select(x => new { x.Id, Title = x.Name + " " + x.Lastname }), "Id", "Title");
BooksIndexViewModel viewModel = new BooksIndexViewModel()
{
Books = _booksRepository.GetAllBooks(),
AuthorOptions = selectList,
authors = _authorRepository.GetAllAuthors(),
Book = _booksRepository.GetBook(Id ?? 0),
publishers = _publisherRepository.GetAllPublishers(),
indexPage = _dataRepository.Generatedata("Knygos", Id,
ControllerContext.RouteData.Values["controller"].ToString())
};
return View(viewModel);
}
The AuthorOptions is what passes the asp-items.
The Form itself uses Book.
Index.cshtml (other lines where removed, only form left)
<form asp-controller="#Model.indexPage.controller"
asp-action="#Model.indexPage.action"
asp-route-id="#if (Model.indexPage.routeId.HasValue) {#Model.indexPage.routeId.Value}" method="post">
<div class="inputs">
<div> <input asp-for="#Model.Book.Title" /> </div>
<div> <select asp-for="#Model.Book.BookAuthors"
asp-items="#Model.AuthorOptions" name="author[]"></select> </div>
<div>
<select asp-for="#Model.Book.PublisherId"
asp-items="#(new SelectList(Model.publishers, "Id", "Title"))"></select>
</div>
<div><input asp-for="#Model.Book.Cost" /></div>
<div><input asp-for="#Model.Book.Code" /></div>
<div><input asp-for="#Model.Book.InvNr" /></div>
<div><input asp-for="#Model.Book.Description" /></div>
</div>
<button type="submit">Save</button>
</form>
The line that im after is <select asp-for="#Model.Book.BookAuthors" asp-items="#Model.AuthorOptions" name="author[]"></select>. It, and the entire Form, gets data form my repository.
The repository
public Book GetBook(int Id)
{
return db.Books.Include(x => x.BookAuthors).SingleOrDefault(x => x.Id == Id);
}
The Value inside the drop-down is AuthorId, the BookAuthors inside the Book model is a IList and connected to a BookAuthor model:
public class BookAuthor
{
public int BookId { get; set; }
public Book Book { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
}
So the problem is, why whenever i get the Book's data (from my Id) all the fields (including PublisherID that is a drop-down but single-to-single connection) gets selected BUT my Authors drop-down does not? What am I missing?
EDIT 1
By changing asp-for="#Model.Book.BookAuthors" => asp-for="#Model.Book.BookAuthors[0].AuthorId" Does the Trick in order to get selected BUT if the book data has more then 1 author, only 1 author is selected from drop-down meniu. + the drop-down becomes no longer multi-select but can be overridden by adding attribute multiple but still only select 1 item from the drop-down menu.
Figured out a trick.
In a viewModel created a IList of integer public IList<int> AuthorIds. inside the .cshtml, int the asp-for="" used the newly created integer list AuthorIds. Inside the controller, the AuthorIds in the ViewModel gets passed with _booksRepository.GetBook(Id).BookAuthors.Select(x => x.AuthorId).ToList();
So the project looks like this:
Controller
public ViewResult Index(int? Id)
{
BooksIndexViewModel viewModel = new BooksIndexViewModel()
{
Books = _booksRepository.GetAllBooks(),
AuthorOptions = new SelectList(_authorRepository.GetAllAuthors()
.Select(x => new { x.Id, Title = x.Name + " " + x.Lastname }), "Id", "Title"),
Book = _booksRepository.GetBook(Id),
publishers = _publisherRepository.GetAllPublishers(),
indexPage = _dataRepository.Generatedata("Knygos", Id,
ControllerContext.RouteData.Values["controller"].ToString())
};
if (Id != null)
viewModel.AuthorIds = _booksRepository.GetBook(Id).BookAuthors.Select(x => x.AuthorId).ToList();
return View(viewModel);
}
cshtml
<form asp-controller="#Model.indexPage.controller" asp-action="#Model.indexPage.action"
asp-route-id="#if (Model.indexPage.routeId.HasValue) {#Model.indexPage.routeId.Value}"
method="post" class="form grid">
<div class="inputs">
<div><input asp-for="#Model.Book.Title" class="w100" /></div>
<div><select asp-for="#Model.AuthorIds" asp-items="#Model.AuthorOptions"
name="author[]" multiple></select></div>
<div><select asp-for="#Model.Book.PublisherId"
asp-items="#(new SelectList(Model.publishers, "Id", "Title"))">
</select></div>
<div><input asp-for="#Model.Book.Cost" /></div>
<div><input asp-for="#Model.Book.Code" /></div>
<div><input asp-for="#Model.Book.InvNr" /></div>
<div><input asp-for="#Model.Book.Description" /></div>
</div>
<button type="submit">Save</button>
</form>
Nothing else has changed.

Image Browser Asp.net MVC 5

I trying to create ImageBrowser in Asp.net MVC 5. Problem is when I try to switch to another picture.
Here's my code:
In View:
#model Katalog.Models.Model
#{
Model.enumerator = 0;
int count = Model.ImageList.Count;
int index = 1;
}
....
<table>
<tbody>
<tr>
<td> #index/#count </td>
....
</tr>
<tr>
#using (Html.BeginForm("previous", "Home",FormMethod.Post))
{
<td>
<input type="hidden" name="number" value="1" />
<input value="<" type="submit" onclick="ImageLeft()" class="buttonLeftRight"/>
</td>
}
<td>#{Html.RenderPartial("~/Views/Shared/ImageViews.cshtml", Model);}</td>
<td>
#using (Html.BeginForm("next", "Home", FormMethod.Post))
{
#Html.HiddenFor(a => a.ImageList)
#Html.HiddenFor(a => a.enumerator)
<input type="submit" class="buttonLeftRight" onclick="ImageRight()"/>
}
</td>
</tr>
</tbody>
</table>
....
<script>
function ImageRight()
{
#{ Model.enumerator++; }
}
</script>
My Controller
....
public ActionResult next(Katalog.Models.Model model)
{
model = MyModel;
return View("Searcher",model);
}
....
and my PartialView:
#model Katalog.Models.Model
<img id="foto" class="imgFinded" src="#Model.ImageList[#Model.enumerator]"/>
When I click Next button my model.ImageList is empty. Why?
The reason your models ImageList property is null is because your generating a hidden input #Html.HiddenFor(a => a.ImageList) which generates
<input name="ImageList" value="System.Collections.Generic.List[]String" .. />
which will not bind to your collection in the POST method (when something is not binding, always insect the name and value attribute of the form controls your generating.
In order to bind to that list you would need to generate an input for each item in the list using a loop.
The other issue is that your scripts does nothing at all. Your model is server side code, and you cannot increment the value of a model property using javascript - you need to send a request to the controller to do that.
Since you sending the collection of images to the view, there is no need to make a request back to the server - you can just update the src attribute of the <img> tag.
Change the model to
public class Model
{
public int InitialIndex { get; set; }
public int ImageCount { get { return ImageList.Count; } }
public List<string> ImageList { get; set; }
}
and then the view can be just (the partial is unnecessary)
<img id="foto" class="imgFinded" src="#Model.ImageList[#Model.InitialIndex ]"/>
<button type="button" id="previous">Previous</button>
<button type="button" id="next">Next</button>
and the scripts
var imagelist = #Html.Raw(Json.Encode(Model.ImageList));
var index = #Html.Raw(Json.Encode(Model.InitialIndex));
var max = #Html.Raw(Json.Encode(Model.ImageCount));
var image = $('#foto');
// Set the initial state of the buttons
if (index === 0) {
$('#previous').prop('disabled', true);
} else if (index === max) {
$('#previous').prop('disabled', true);
}
$('#next').click(function() {
$('#previous').prop('disabled', false);
index++;
image.attr('src', imagelist[index]);
if (index === max) {
$(this).prop('disabled', true);
}
})
$('#previous').click(function() {
$('#next').prop('disabled', false);
index--;
image.attr('src', imagelist[index]);
if (index === 0) {
$(this).prop('disabled', true);
}
})
The code #{Model.enumerator++;} and #{Model.enumerator--;} within the two Javascript functions is server side code so it will only be executed once when the view is rendering on the server and before it is passed to the client browser. So triggering the onclick="ImageRight()" by pressing the submit button will not change the server side value.
You could instead try to post the current index to the action in your controller and increment or decrement it depending on which action has been invoked.
#using (Html.BeginForm("Next", "Home", FormMethod.Post))
{
#Html.HiddenFor(a=>a.CurrentIndex)
<input type="submit" class="buttonRightLeft"/>
}
#using (Html.BeginForm("Previous", "Home", FormMethod.Post))
{
#Html.HiddenFor(a=>a.CurrentIndex)
<input type="submit" class="buttonLeftRight"/>
}
public ActionResult Next(int CurrentIndex)
{
// Get the NEXT image and return as model
model = MyModel;
return View("Searcher",model);
}
public ActionResult Previous(int CurrentIndex)
{
// Get the PREVIOUS image and return as model
model = MyModel;
return View("Searcher",model);
}

How to link 2 actions to 1 form

I'm not sure if what I'm asking is even possible. I have a form with a checkbox list and button above it. The user selects from the list and then clicks the button and it writes to the db. Now i would like to add a second button that will do something different to the selection. How would I go about about linking this second button to a different action?
current code:
#using (Html.BeginForm("RemoveFromAvailable", "GroupPlayManager", new { id = Model.Id, slug = Model.Slug, innerid = Model.GroupPlayManagerId }, FormMethod.Post, null))
{
<div class="hMarginBottom15">
<input type="hidden" class="groupPlay-id" name="GroupPlayId" value="#Model.GroupPlayInput.Id" />
<input type="hidden" name="GroupPlayManagerId" value="#Model.GroupPlayManagerId" />
<input type="hidden" name="GroupPlayDateTime" value="#Model.GroupPlayInput.GroupPlayDate" />
<button name="RemoveFromAvailable" id="unavailableButton" class="btn btn-danger" disabled="disabled">Remove</button>
</div>
#Html.EditorFor(
m => m.AvailablePlayers,
"BootstrapHorizontalCheckboxList",
new
{
data = Model.AvailablePlayersDates.Select(tm => new SelectListItem
{
Text = tm.Name,
Value = tm.Id,
}).ToList(),
chunksize = 1,
isRequired = true,
displaylabel = false,
cssClass = "col-md-12"
})
}
Name your buttons and then branch in your action accordingly. For example:
<button type="submit" name="_Save">Save</button>
<button type="submit" name="_SomethingElse">Something Else</button>
Then, in your action:
if (Request["_Save"] != null))
{
// save
}
else if (Request["_SomethingElse"] != null))
{
// do something else
}
The key will only be present if the user clicked that particular button.

Using list in a model value in LINQ query

I am at very basic stage of asp.net MVC development. So sometimes I struggle with simple LINQ queries to work.
scenario-
I have A page that has some Image and comment on that Image by users (Just Like a post on facebook containing comments from users).
So I am saving those comments from the textarea and sending Image ID via Ajax query.
Here Is my controller action method-
Saving comment-
[HttpPost]
public void SaveComment(CardModel card) {
CardCommentTable commenttable = new CardCommentTable();
commenttable.CardComment = card.cardComment;
commenttable.FKcardID = card.cardID;
db.CardCommentTables.InsertOnSubmit(commenttable);
db.SubmitChanges();
}
This Comment is saved in CardCommentTable that has foreign key reference of Table in that Image is saved.
Rendering Image and other fields on view page-
This query renders Image and other fields that make it An Image post. Like title, dateofsubmit, Like etc.
public ActionResult CardDetails(CardModel card) {
var cardDetail = (from u in db.CardTables
where u.CardID == card.cardID
select new CardModel {
cardID = u.CardID,
cardHashCode = u.CardHashCode,
cardDate = u.CardDate,
cardFileName = u.CardFileName,
cardFilePath = u.CardFilePath,
cardTitle = u.CardTitle
}).ToList();
return View(cardDetail);
}
Now In cardTable I have one more column named cardComment in that I want to show all those saved comments from table CardCommentTable.
So I tried-
public ActionResult CardDetails(CardModel card) {
var allsavedcomments= (from u in db.CardCommentTables
where u.FKcardID == card.cardID
select u).ToList();
var cardDetail = (from u in db.CardTables
where u.CardID == card.cardID
select new CardModel {
cardID = u.CardID,
cardHashCode = u.CardHashCode,
cardDate = u.CardDate,
cardFileName = u.CardFileName,
cardFilePath = u.CardFilePath,
cardTitle = u.CardTitle,
cardComment = allsavedcomments // Trying to render all saved coments here.
}).ToList();
return View(cardDetail);
}
View-
#model IEnumerable<FunRanger.Models.CardModel>
#foreach (var item in Model) {
<script type="text/javascript">
$(function () {
$('#save-comment').click(function () {
var textareavalue = $('#textarea-comment').val();
$.ajax({
url: '/Home/SaveComment/',
type: 'post',
data: '&cardComment=' + textareavalue + '&cardID=' + '#item.cardID',
success: function (data) {
$('#all-comments').append(data);
}
});
});
});
</script>
using (Html.BeginForm()) {
#Html.ValidationSummary(true)
#if (Model != null) {
<h2 class="header-wrapmain">
#item.cardTitle
</h2>
#item.cardDate.ToShortDateString()
<img src="#item.cardFilePath" />
<a href="#" class="#item.cardHashCode" rel="tooltip" data-placement="bottom" title="Filter by #item.cardHashCode">
##item.cardHashCode</a>
}
else {
<div class="alert alert-danger">
No More items to preview
</div>
}
}
<textarea class="span12" rows="5" id="textarea-comment" style="resize: none" placeholder="Enter a comment..."></textarea>
Save comment
<ol>
<li>
#item.cardComment
</li>
</ol>
}
How can I insert List result in a column here.
How do I show all saved comments with this above query?
Thanks for any help.
I slightly renovated your code with Foreign key relations ship. This will save your from using two different queries to your database (like what you are doing now).
So if you Database Model looks like this -
Then you should have one viewmodel in your code in this way -
public class ImageViewModel
{
public string ImageId { get; set; }
public string ImageUrl { get; set; }
public List<string> Comments { get; set; }
}
And your controller action which will return all the results should be like this -
public class ListController : Controller
{
public ActionResult Index()
{
ImageViewModel model;
using (SampleEntities entities = new SampleEntities())
{
model = (from p in entities.Images
where p.ImageId == "1"
select new ImageViewModel()
{
ImageId = p.ImageId,
ImageUrl = p.ImageUrl,
Comments = p.ImageComments.Select(pa => pa.Comment).ToList()
}).FirstOrDefault();
}
return View(model);
}
}
Finally the view which will display all the Image results -
#model MVC.Controllers.ImageViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
<h4>ImageViewModel</h4>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ImageId)
</dt>
<dd>
#Html.DisplayFor(model => model.ImageId)
</dd>
<dt>
#Html.DisplayNameFor(model => model.ImageUrl)
</dt>
<dd>
#Html.DisplayFor(model => model.ImageUrl)
</dd>
<br/>
#foreach (var item in Model.Comments)
{
#item <br/>
}
</dl>
</div>
Output would be -
Your cardComment property is a list of strings; it needs to be iterated in order to be displayed. Replace:
<ol>
<li>
#item.cardComment
</li>
</ol>
with:
<ol>
#foreach (var singleComment in Model.cardComment)
{
<li>#singleComment </li>
}
</ol>

Categories