In my Asp.Net MVC application, I passed the view model to the main view to collect the data from the user.
There is a section to upload files.
When I attached a file and submitted the data to the controller, I could see all the data filled from the view but it's not showing the attached file.
I also checked by putting alerts to the script whether it collects the attachments, It gets the file. But won't pass to the controller.
Can anyone tell me how to do this correctly?
I also mentioned this on the top of the view
#using (Html.BeginForm("Create", "Performance", FormMethod.Post, new { enctype = "multipart/form-data" }))
This is the top of the view
#model IEnumerable<KPIModels.ViewModels.MainDetailsVM>
This is the model
public class SelfImprovementMainVM
{
public int SelfImpId { get; set; }
public int EmpMarks { get; set; }
public int SupervisorMarks { get; set; }
public string Comments { get; set; }
public byte[] Attachment { get; set; }
public string FileType { get; set; }
public string SelfImName { get; set; }
}
this is the view
<div class="col-md-10"> #Html.Label("Attach your files") </div>
<div class="col-md-10">
<input type="file" name="ImageData " id="ImageData" onchange="checkImage(this)" /> #Html.ValidationMessageFor(model => model.First().SelfImprovementMainVMList[1].Attachment, "", new { #class = "text-danger" })
</div>
<img id="imageDisplay" src="" alt="" width="100" height="100" class="ml-1" />
< script type = "text/javascript" >
function checkImage(obj) {
var fileExtension = ['jpeg', 'jpg', 'png', 'gif', 'bmp', 'pdf'];
if ($.inArray($(obj).val().split('.').pop().toLowerCase(), fileExtension) == -1) {
msgDisplay('error', 'Upload Error', 'Only .jpeg, .jpg, .png, .gif, .bmp ,.pdf formats are allowed.');
$("#imageDisplay").prop('src', '');
} else {
var files = obj.files;
var reader = new FileReader();
name = obj.value;
reader.onload = function (e) {
$("#imageDisplay").prop('src', e.target.result);
alert(e.target.result);
};
reader.readAsDataURL(files[0]);
alert(files[0]);
}
}
<
/script>
In controller, this file returns null
HttpPostedFileBase file = Request.Files["ImageData"];
if (file.ContentLength > 0) {
selfs.MainDetailID = mainDetails.Id;
selfs.Attachment = ConvertToBytes(file);
selfs.FileType = file.FileName;
dbs.SelfImprovementMain.Add(selfs);
dbs.SaveChanges();
}
use IFormFile interface
public class SelfImprovementMainVM
{
public int SelfImpId { get; set; }
public int EmpMarks { get; set; }
public int SupervisorMarks { get; set; }
public string Comments { get; set; }
public IFormFile Attachment { get; set; }
public string FileType { get; set; }
public string SelfImName { get; set; }
}
do not make it byte[] and send it with js let asp.net do it for you
Related
I have this model,and table i db with data
public class FileType
{
public int Id { get; set; }
public string FileTypeName { get; set; }
}
I have upload form and this viewmodel for upload
public List<FileModel> Files { get; set; }
public string Name { get; set; }
public string Extension { get; set; }
public string Description { get; set; }
public string Author { get; set; }
public string Year { get; set; }
public string FilePath { get; set; }
public string PublishedOn { get; set; }
public int DownloadCounter { get; set; }
public Genres Genre { get; set;}
public int FileTypeId { get; set; }
public List<SelectListItem> FtypeList { get; set; }
public FileType FileT { get; set; }
I generate dropdown list to pick FileType with this code :
public IActionResult Index()
{
var vm = new FileUploadViewModel();
vm.FtypeList = context.FileTypes
.Select(a => new SelectListItem()
{
Value = a.Id.ToString(),
Text=a.FileTypeName
}).ToList();
ViewBag.Message = TempData["Message"];
return View(vm);
}
And in view i have this
<div class="form-group row">
<label asp-for="FileT" class="col-sm-2 col-form-label"> </label>
<div class="col-sm-10">
<select asp-for="FileT" class="custom-select mr-sm-2" asp-items="#Model.FtypeList"></select>
</div>
</div>
In the HttpPost action i do this
[HttpPost]
public async Task<IActionResult> Index(List<IFormFile> files, string description,DateTime PublishedOn,string Author,string Name,FileType Ftype)
{
foreach (var file in files)
{
var basePath = Path.Combine(Directory.GetCurrentDirectory() + "\\Files\\");
bool basePathExists = System.IO.Directory.Exists(basePath);
if (!basePathExists) Directory.CreateDirectory(basePath);
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var filePath = Path.Combine(basePath, file.FileName);
var extension = Path.GetExtension(file.FileName);
DateTime dateTime = DateTime.UtcNow;
var createdOn = dateTime.ToShortDateString();
if (!System.IO.File.Exists(filePath))
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
var fileModel = new FileModel
{
Year =createdOn,
PublishedOn = PublishedOn.ToShortDateString(),
FileType = file.ContentType,
Extension = extension,
Name = Name,
Description = description,
FilePath = filePath,
Author=Author,
Ftype=Ftype,
};
context.Files.Add(fileModel);
context.SaveChanges();
}
}
TempData["Message"] = "File successfully uploaded to File System.";
return RedirectToAction("Index","Home");
}
But when i upload file it doesnt get the selected value from dropdown list it create new item in the selected list.For example i have only 4 FileTypes in table if i select item with value=3 when file is uploaded to db in the table with uploaded files Ftype = 5 and it create new row in FileTypes table with Id = 5.
fix your view, You have to use FileTypeId for select
<select asp-for="FileTypeId" class="custom-select mr-sm-2" asp-items="#Model.FtypeList"></select
......
and since you are using post your action input parameter should be the same as model
public async Task<IActionResult> Index(FileModel viewModel)
......
According to your FileUploadViewModel view model, I assume the FileTypeId is the user selected file type id value, right?
If that is the case, I suggest you could modify your code as below:
<div class="form-group row">
<label asp-for="FileTypeId" class="col-sm-2 col-form-label"> </label>
<div class="col-sm-10">
<select asp-for="FileTypeId" class="custom-select mr-sm-2" asp-items="#Model.FtypeList"></select>
</div>
</div>
Then, in the action method add the FileTypeId parameter, like this:
[HttpPost]
public async Task<IActionResult> CreateFile(List<IFormFile> files, string description, DateTime PublishedOn, string Author, string Name, FileType Ftype, int FileTypeId)
{
Then, when you create FileModel, you could check if the FileType exists or not based on the FileTypeId paramter. Check the following code:
var fileModel = new FileModel
{
Year =createdOn,
PublishedOn = PublishedOn.ToShortDateString(),
FileType = file.ContentType,
Extension = extension,
Name = Name,
Description = description,
FilePath = filePath,
Author=Author,
};
//Check if the FileType exists or not, if exists, get the existing FileType and assign it to the new fileModel. if not exists, create a new FileType Model and assign it to the new fileModel.
var filetype = context.FileTypes.Where(c => c.Id == FileTypeId).FirstOrDefault()
if (filetype!= null)
{
fileModel.Ftype = filetype; //using the existing file type.
}
else
{
var newFileType = new FileType();
fileModel.Ftype = newFileType ; //using the new file type.
}
context.Files.Add(fileModel);
context.SaveChanges();
FileType = file.ContentType,
Besides, it seems that the FileModel also contains the FileType, not sure the issue relate it or not, if you are using the Ftype property to set the file type, perhaps there is no need to set the FileType property.
I'm trying to present a table with a list of rows from the database, as well as a small form option for the user to add an additional db row. I made two Models in order to both hold the table rows and capture the form. I'm not having problems with the table model, just the form model.
So I'm confident the problem is in my Controller; I am new to MVC and this is the first time I've seen two models in the same VM... I've been going back and forth making small changes to things, but I keep getting a Null Reference Error in my Controller.
VM:
namespace User.ViewModel
{
public class UploadDocumentTemplatesViewModel
{
public string TemplateName { get; set; }
public string Comments { get; set; }
}
public class TemplateModel
{
public UploadDocumentTemplatesViewModel NewTemplate { get; set; }
public List<UploadDocumentTemplatesViewModel> Templates { get; set; }
}
}
View (UploadDocumentTemplates.cshtml):
#using (Html.BeginForm("AddNewTemplate", "User", FormMethod.Post, new { enctype = "multipart/form-data", id = "NewTemplateForm"}))
{
#Html.AntiForgeryToken()
<div>
<input type="text" class="form-control" rows="5" id="TemplateName" value="#Model.NewTemplate.TemplateName">
<label for="comments">Comments:</label>
<textarea class="form-control" rows="5" id="comments" name="#Model.NewTemplate.Comments"></textarea>
<button id="AddTemplate" onclick="AddNewTemplate()" name="Add Template">Add Template</button>
</div>
}
<table>
<tbody>
#{ foreach (var template in Model.Templates)
{
<tr id="tr_#template.DocumentTemplateId">
<td>#template.TemplateName</td>
<td>#template.Comments </td>
<td>#template.IsActive </td>
}
<script>
function AddNewTemplate() {
$("#NewTemplateForm").submit();
}
</script>
Controller:
public class UserController : Controller
{
public ActionResult UploadDocumentTemplates()
{
var model = entity.DocumentTemplates.Select(x => new UploadDocumentTemplatesViewModel()
{
DocumentTemplateId = x.DocumentTemplateId,
TemplateName = x.TemplateName,
Comments = x.Comments,
});
var _obj = new TemplateModel();
var templatelist = _entities.GetTemplates();
_obj.Templates = new List<UploadDocumentTemplatesViewModel>();
foreach (var template in templatelist)
{
_obj.Templates.Add(new UploadDocumentTemplatesViewModel()
{
TemplateName = template.TemplateName,
Comments = template.Comments,
});
}
_obj.NewTemplate = new UploadDocumentTemplatesViewModel();
return View(_obj);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddNewTemplate(TemplateModel vModel)
{
var template = new DocumentTemplates();
template.TemplateName = vModel.NewTemplate.TemplateName;
template.Comments = vModel.NewTemplate.Comments;
entity.DocumentTemplates.Add(template);
entity.SaveChanges();
return View("~/User/UploadDocumentTemplates.cshtml", vModel);
}
}
I hit a Null Reference at this line in my Post method in the Controller:
template.TemplateName = vModel.NewTemplate.TemplateName;
The vModel.NewTemplate.TemplateName is null. Can anyone help me with this?
Thank you so much!
SOLUTION:
The NRE did get fixed with Andy's help (see answer). My further issue was fixed after I populated the new VM with the fields I was using in my form.
namespace Example.Areas.ViewModel
{
public class UploadDocumentTemplatesViewModel
{
public long DocumentTemplateId { get; set; }
public string TemplateName { get; set; }
public string Comments { get; set; }
}
public class TemplateModel
{
public string TemplateName { get; set; }
public string Comments { get; set; }
public HttpPostedFileBase TemplateFile { get; set; }
public List<UploadDocumentTemplatesViewModel> Templates { get; set; }
}
}
In the controller I populated the TemplateModel and sent that to the View:
public ActionResult UploadDocumentTemplates()
{
var templateList = Repository.GetTemplates();
var _obj = new TemplateModel
{
Templates = templateList.Select(x => new UploadDocumentTemplatesViewModel()
{
DocumentTemplateId = x.DocumentTemplateId,
TemplateName = x.TemplateName,
Comments = x.Comments
}).ToList()
};
return View(_obj);
}
Then I put #using Example.Areas.ViewModel.TemplateModel on my View and used Model.Templates for the table, and Model.TemplateName and Model.Comments in the form.
Add a breakpoint in the line where you hit the Null Reference and check if vModel.NewTemplate has a valid instance.
You can add a constructor in TemplateModel class to create a new instance of UploadDocumentTemplatesViewModel()
namespace User.ViewModel
{
public class UploadDocumentTemplatesViewModel
{
public string TemplateName { get; set; }
public string Comments { get; set; }
}
public class TemplateModel
{
public TemplateModel()
{
NewTemplate = new UploadDocumentTemplatesViewModel();
}
public UploadDocumentTemplatesViewModel NewTemplate { get; set; }
public List<UploadDocumentTemplatesViewModel> Templates { get; set; }
}
}
OR
create an instance after instantiating template:
var template = new DocumentTemplates();
template.NewTemplate = new UploadDocumentTemplatesViewModel();
I have a web application to upload image to database and to retreive them.
public class ImageGallery
{
[Key]
public int ImageID { get; set; }
public int ImageSize { get; set; }
public string FileName { get; set; }
public byte[] ImageData { get; set; }
[Required(ErrorMessage="Please select Image File")]
public HttpPostedFileBase file { get; set; }
}
and my database context class is something like this
public class MyDatabaseEntities : DbContext
{
public DbSet<ImageGallery> ImageGalleries { get; set; }
}
and here is my controller
public ActionResult Upload()
{
return View();
}
[HttpPost]
public ActionResult Upload(ImageGallery IG)
{
IG.FileName = IG.File.FileName;
IG.ImageSize = IG.File.ContentLength;
byte[] data = new byte[IG.File.ContentLength];
IG.File.InputStream.Read(data, 0, IG.File.ContentLength);
IG.ImageData = data;
using(MyDatabaseEntities dc = new MyDatabaseEntities())
{
dc.ImageGalleries.Add(IG);
dc.SaveChanges();
}
return RedirectToAction("Gallery");
}
now when i try to upload the image it giving me following error
EntityType 'HttpPostedFileBase' has no key defined. Define the key for this EntityType. HttpPostedFileBases: EntityType: EntitySet 'HttpPostedFileBases' is based on type 'HttpPostedFileBase' that has no keys defined.
I have seen one of question on stack overflow-----'HttpPostedFileBase' has no key defined. Define the key for this EntityType. I tried the solution but did not get any success.
I was following this blog for this purpose------
http://dotnetawesome.com/mvc/how-to-upload-image-to-database-and-show-in-view-without-image-handler
Try this
[NotMapped]
public HttpPostedFileBase File { get; set; }
This will not map to the database.
The error occurs because their is no datatype HttpPostedFileBase in your table
You cannot store HttpPostedFileBase in a database field (its a complex object containing multiple properties). You could exclude this using the [NotMapped] attribute, however your model and your view really have no relationship (your not including any inputs for the other properties of your model).
Instead your view can be just
#using (Html.BeginForm("Upload", "ImageGallery", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type = "submit" value="Upload" />
}
and change the POST method to
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if (file.ContentLength > 0) // check a file was selected
{
// Initialize a new instance of the data model and set its properties
ImageGallery model = new ImageGallery()
{
FileName = file.FileName,
ImageSize = file.ContentLength,
....
};
.... // save and redirect
}
else {
// add a model state error and return the view?
}
}
Simply try a new view model with properties like this-----
public class ImageViewModel
{
public int ImageID { get; set; }
public int ImageSize { get; set; }
public string FileName { get; set; }
public byte[] ImageData { get; set; }
public HttpPostedFileBase File { get; set; }
}
and change your controller like this-----
public ActionResult Upload(HttpPostedFileBase file)
{
ImageGallery IG = new ImageGallery();
IG.FileName = file.FileName;
IG.ImageSize = file.ContentLength;
byte[] data = new byte[file.ContentLength];
file.InputStream.Read(data, 0, file.ContentLength);
IG.ImageData = data;
var model = new ImageViewModel
{
FileName = file.FileName,
ImageSize = file.ContentLength,
ImageData = data,
File = file
};
using(MyDatabaseEntities dc = new MyDatabaseEntities())
{
dc.ImageGalleries.Add(IG);
dc.SaveChanges();
}
return View(model);
}
}
}
and change your view page like this------
#model Image.Models.ImageViewModel
<h2>Upload</h2>
#using (Html.BeginForm("Upload", "ImageGallery", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<table>
<tr>
<td>Select File : </td>
<td>
#Html.TextBoxFor(Model => Model.File, new { type = "file" })
#Html.ValidationMessage("CustomError")
</td>
<td>
<input type="submit" value="Upload" />
</td>
</tr>
</table>
}
I have the following form:
#model Teesa.Models.SearchModel
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { id = "SearchForm" }))
{
<div class="top-menu-search-buttons-div">
#if (!MvcHtmlString.IsNullOrEmpty(Html.ValidationMessageFor(m => m.SearchText)))
{
<style type="text/css">
.top-menu-search-text
{
border: solid 1px red;
}
</style>
}
#Html.TextBoxFor(q => q.SearchText, new { #class = "top-menu-search-text", id = "SearchText", name = "SearchText" })
#Html.HiddenFor(q=>q.Page)
<input type="submit" value="search" class="top-menu-search-submit-button" />
</div>
<div id="top-menu-search-info" class="top-menu-search-info-div">
Please Select one :
<hr style="background-color: #ccc; height: 1px;" />
<div class="top-menu-search-info-checkbox-div">
#Html.CheckBoxFor(q => q.SearchInBooks, new { id = "SearchInBooks", name = "SearchInBooks" })
<label for="SearchInBooks">Books</label>
</div>
<div class="top-menu-search-info-checkbox-div">
#Html.CheckBoxFor(q => q.SearchInAuthors, new { id = "SearchInAuthors" })
<label for="SearchInAuthors">Authors</label>
</div>
<div class="top-menu-search-info-checkbox-div">
#Html.CheckBoxFor(q => q.SearchInTags, new { id = "SearchInTags" })
<label for="SearchInTags">Tags</label>
</div>
}
and the following Controller and Models :
namespace Teesa.Models
{
public class SearchModel
{
[Required(ErrorMessage = "*")]
public string SearchText { get; set; }
public bool SearchInTags { get; set; }
public bool SearchInAuthors { get; set; }
public bool SearchInBooks { get; set; }
public int Page { get; set; }
public List<SearchBookModel> Result { get; set; }
public List<SimilarBookModel> LatestBooks { get; set; }
}
public class SearchBookModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public string Summary { get; set; }
public List<Tags> Tags { get; set; }
public string StatusName { get; set; }
public string SubjectName { get; set; }
public string ThumbnailImagePath { get; set; }
public string BookRate { get; set; }
public string RegistrationDate { get; set; }
public int NumberOfVisit { get; set; }
}
}
[HttpGet]
public ActionResult Index(SearchModel model)
{
FillSearchModel(model);
if (ModelState.IsValid)
{
string page = model.Page;
DatabaseInteract databaseInteract = new DatabaseInteract();
model.Result = new List<SearchBookModel>();
List<Book> allBooks = databaseInteract.GetAllBooks();
List<Book> result = new List<Book>();
#region
if (model.SearchInTags)
{
var temp = (from item in allBooks
from tagItem in item.Tags
where tagItem.Name.Contains(model.SearchText)
select item).ToList();
result.AddRange(temp);
}
if (model.SearchInBooks)
{
var temp = (from item in allBooks
where item.عنوان.Contains(model.SearchText)
select item).ToList();
result.AddRange(temp);
}
if (model.SearchInAuthors)
{
var temp = (from item in allBooks
where item.Author.Contains(model.SearchText)
select item).ToList();
result.AddRange(temp);
}
#endregion
#region Paging
string itemsPerPage = databaseInteract.GetItemsPerPage();
int ItemInPage = int.Parse(itemsPerPage);
var pagingParams = Helpers.SetPagerParameters(page, ItemInPage, result);
ViewBag.AllPagesCount = pagingParams.AllPagesCount;
ViewBag.CurrentPageNumber = pagingParams.CurrentPageNumber;
ViewBag.CountOfAllItems = pagingParams.CountOfAllItems.ToMoneyFormat().ToPersianNumber();
result = pagingParams.ListData as List<Book> ?? result;
#endregion
foreach (var item in result)
{
var bookRate = (item.BookRate == null || item.BookRate.Count == 0)
? 0.0
: item.BookRate.Average(q => q.Rate);
model.Result.Add(new SearchBookModel
{
Author = item.Author,
Id = item.Id,
.
.
.
});
}
}
else
{
model.Result = new List<SearchBookModel>();
}
return View(model);
}
When I submit the form I see the following query strings(Notice the duplicate names) :
http://localhost:2817/Search?SearchText=book&Page=2&SearchInBooks=true&SearchInBooks=false&SearchInAuthors=true&SearchInAuthors=false&SearchInTags=true&SearchInTags=false
But it has to be something like this :
http://localhost:2817/Search?SearchText=book&Page=2&SearchInBooks=true&SearchInAuthors=true&SearchInTags=true
How can I fix it ?
Thanks
Html.Checkbox (and the related For... methods) generate a hidden input for false, and the checkbox for true. This is to ensure that model binding works consistently when binding.
If you must get rid of "false" items resulting from the hidden inputs, you'll need to construct the checkbox inputs yourself (using HTML and not the helper).
<input type="checkbox" id="SearchInBooks" name="SearchInBooks">
Why dont your create a Post Method with a matching name to the Get method. This will ensure that the code is much easier to debug. As you will not have a huge function to go through trying to find problems like this.
I cannot find a where your getting the duplicate url query strings from though.
This will also allow you to bind your results back to the model.
If you want the model binding to happen successfully then you have to go with this way because that is the nature of the Html.CheckBox/Html.CheckBoxFor methods they will render a hidden field as well.
I would suggest rather go with POST to make your life easy. If you still want to use GET then you have to use checkbox elements directly but you have to take care of the model binding issues. Not all the browsers returns "true" when the checkbox is checked for ex. firefox passes "on" so the default model binder throws an error.
Other alternate options is you can go for custom model binder or you can submit the form using jquery by listening to the submit event.
I have this problem where i want to make 7 dropdowns for each day of the week.
In each one of those dropdowns i wish to add the same data.
My ViewModel:
public class WeekDienstCreateViewModel
{
public WeekDienst weekDienst {get; set;}
public List<DienstPerWeekDienst> diensten { get; set; }
public WeekDienstCreateViewModel() { }
}
My Create Method in Controller:
As u can see I add everything allready except DienstId which is want to add with my dropdowns.
public ActionResult Create(int id)
{
WeekDienst wd = _service.FindWeekDienst(id);
WeekDienstCreateViewModel vm = new WeekDienstCreateViewModel();
vm.diensten = new List<DienstPerWeekDienst>();
vm.weekDienst = wd;
for (int i = 1; i <= 7; i++)
{
DienstPerWeekDienst dpwd = new DienstPerWeekDienst();
dpwd.volgnummer = i;
dpwd.WeekDienstId = wd.Id;
vm.diensten.Add(dpwd);
}
ViewBag.Diensten = _service.DienstenList(wd.AfdelingId);
return View(vm);
}
Classes:
public class DienstPerWeekDienst
{
[Key]
public int Id { get; set; }
[Required]
public int WeekDienstId { get; set; }
[Required]
public int DienstId { get; set; }
[Required]
[Range(1, 7)]
public int volgnummer { get; set; }
[ForeignKey("WeekDienstId")]
public virtual WeekDienst WeekDienst { get; set; }
[ForeignKey("DienstId")]
public virtual Dienst Dienst { get; set; }
public virtual ICollection<WeekDienst> WeekDiensten { get; set; }
}
public class WeekDienst
{
[Key]
public int Id { get; set; }
[Required]
public int AfdelingId { get; set; }
[Required]
[StringLength(5, ErrorMessage = "Value for {0} cannot exceed {1} characters.")]
[RegularExpression(#"^[a-zA-Z0-9]{5}$", ErrorMessage = "Verplicht 5 cijfers lang.")]
public string code { get; set; }
[DisplayName("Template")]
public bool template { get; set; }
[ForeignKey("AfdelingId")]
public virtual Afdeling Afdeling { get; set; }
}
And in my view i wish to create 7 dropdowns where i put in all my "Diensten" (class Dienst, fk in DienstPerWeekDienst). When I choose 1 i wish to add the "DienstId" into the "DienstPerWeekDienst" class.
So in my View i got this:
#foreach (var day in Model.diensten)
{
var currentDay=day;
#Html.DropDownListFor(currentDropDown=>currentDay, new SelectList(ViewBag.Diensten, "Value", "Text"))
}
I Wish to postback the chosen "Diensten" and create the "WeekDienst" but now i am just posting a null "DienstPerDienstWeekCreateViewModel". How am I able to fix this?
Thanks in Advance
FIX (Thanks to Siva Gopal)
I fixed this by doing:
#for (int i = 0; i < #Model.diensten.Count; i++)
{
#Html.HiddenFor(m => (m.diensten[i].volgnummer))
#Html.HiddenFor(m => (m.diensten[i].WeekDienstId))
#Html.DropDownListFor(m=> (m.diensten[i].DienstId), new SelectList(ViewBag.Diensten, "Value", "Text"))
}
You may try using
#foreach (var day in Model.diensten)
{
var currentDay=day;
#Html.DropDownListFor(currentDropDown=>currentDay, new SelectList(ViewBag.Diensten, "PropertyName_Holding_Value", "PropertyName_Holding_DisplayText"), new { })
} //This uses the Lambda Expression. Your dropdown Name/Id would be 1,2,3 etc. based on currentDay value.
OR
#foreach (var day in Model.diensten)
{
var currentDay=day;
var dropdownName=string.Format("diensten[{0}]",day-1); //If you want to model bind the selected dropdown value to input entity in POST request. The final dropdownName format should match the hierarchy of the property inside input entity/object. Even without this name formation, you can still POST the selected value back using Jquery/Javascript.
#Html.DropDownList(dropdownName, new SelectList(ViewBag.Diensten, "PropertyName_Holding_Value", "PropertyName_Holding_DisplayText"), new {})
} //
Note for Value Post back/model bind on full Page submit:
To be able to model bind/POST back values to the server, the html element names corresponding to the properties should be rendered as follows: Suppose if you display Employee.Department.Name, then name of textbox, displaying the Department Name in View should match Department_ReferenceName_Inside_Employee.Name for model binding.
Model:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public Department EmpDepartment { get; set; }
public List SubOrdinates { get; set; }
}
public class Department
{
public string Name { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
//Prepare the model and send it to the view
Employee emp = new Employee { EmpDepartment = new Department { Name = "IT" } };
emp.SubOrdinates = new List<Employee> { new Employee { Name = "Emp1" }, new Employee { Name = "Emp2" } };
return View(emp);
}
[HttpPost]
public ActionResult Index(Employee emp)
{ //Put a break-point here and see how the modified values in view are flowing into emp..
return View(emp);
}
public ActionResult About()
{
return View();
}
}
View:
#model MvcApplication.Models.Employee
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.EmpDepartment.Name)
#Html.LabelForModel("SubOrdinates :")
for (int i = 0; i < #Model.SubOrdinates.Count; i++)
{
#Html.TextBoxFor(m => (m.SubOrdinates[i].Name))
}
<input type="submit" name="name" value="Submit" /> }
ViewSource/PageSource:
The above text box syntax will be rendered as :
<input id="EmpDepartment_Name" name="EmpDepartment.Name" type="text" value="IT" /> <!--See above html : name=EmpDepartment.Name -->
<label for="">SubOrdinates :</label>
<input id="SubOrdinates_0__Name" name="SubOrdinates[0].Name" type="text" value="Emp1" />
<input id="SubOrdinates_1__Name" name="SubOrdinates[1].Name" type="text" value="Emp2" /> <!--See above html for how collection item Name(s) are being renderd by view engine-->
<input type="submit" name="name" value="Submit" />
#foreach (var day in Model.diensten)
{
var currentDay = day;
#Html.DropDownListFor(x => currentDay, new SelectList(ViewBag.Diensten, "Value", "Text"), new { #id = "DienstList" })
}
List<MvcApplication1.Models.Country> cntry = db.Countries.ToList();
SelectListItem sss = new SelectListItem();
List<SelectListItem> sltst = new List<SelectListItem>();
sss.Text = "Select";
sss.Value = "0";
sltst.Add(sss);
foreach (MvcApplication1.Models.Country s in cntry){
SelectListItem s1 = new SelectListItem();
s1.Text = s.Country1;
s1.Value = Convert.ToString(s.Id);
sltst.Add(s1);}
#Html.DropDownList("country", sltst, new { #id = "country" })