where I have got one textbox and button and when the user entered a value and the press submit button , that values i need to show in Kendo UI Grid in same view ..
for this purpose i have done like this .....
this is my model..
namespace KendoSampleMVCApp.Models
{
public class TextBoxGrid
{
public string EnteredValue { get; set; }
public List<EmployeeDetails> employees;
}
public class EmployeeDetails
{
public string EmployeeId { get; set; }
public string ManagerId { get; set; }
}
}
and this is my controller
namespace KendoSampleMVCApp.Controllers
{
public class EnterValuesGridController : Controller
{
public ActionResult Index( TextBoxGrid model)
{
return View(GetEmployee());
}
[HttpPost]
public ActionResult PostValues(TextBoxGrid model)
{
TempData["enteringValue"] = model.EnteredValue;
return View(model);
}
public IEnumerable<EmployeeDetails> GetEmployee()
{
string enteredValueId =(string) TempData["enteringValue"];
string managerId = "M" +enteredValueId;
List<EmployeeDetails> empdtls = new List<EmployeeDetails>();
EmployeeDetails em1 = new EmployeeDetails();
em1.EmployeeId = enteredValueId;
em1.ManagerId = managerId;
empdtls.Add(em1);
return empdtls;
}
public ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request)
{
return Json(GetOrders().ToDataSourceResult(request));
}
private IEnumerable<EmployeeDetails> GetOrders()
{
return GetEmployee();
}
}
}
and this is my view
#model KendoSampleMVCApp.Models.TextBoxGrid
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("PostValues","EnterValuesGrid",FormMethod.Post))
{
<div>
<fieldset>
<legend>Enter Textbox Value</legend>
<div class="editor-field">
#Html.TextBoxFor(m=>m.EnteredValue)
</div>
<p>
<input type="submit" name="Submitbutton1" value="Submit1" />
</p>
</fieldset>
</div>
}
#model IEnumerable<KendoSampleMVCApp.Models.EmployeeDetails> <----- error at this line
<h2>Index</h2>
#using (Html.BeginForm())
{
#(Html.Kendo().Grid<KendoSampleMVCApp.Models.EmployeeDetails>()
.Name("grid")
.Columns(columns => {
columns.Bound(p => p.EmployeeId).Filterable(false).Width(100);
columns.Bound(p => p.ManagerId).Filterable(false).Width(100);
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Orders_Read", "EnterValuesGrid"))
)
)
}
I am getting error at this line #model IEnumerable<KendoSampleMVCApp.Models.EmployeeDetails>
saying that
Parser Error Message: Only one 'model' statement is allowed in a file.
would any one pls suggest any ideas why i am getting this error ...can't i use two models in same view ....
many thanks ...
EDIT : can i do like this In my model...
public class ParentViewModel
{
public EmployeeDetails EmployeeDetails { get; set; }
public TextBoxGrid TextBoxGrid { get; set; }
}
The answer is no, you can't use two models in one view. And there is no reason why you should need to. The whole point of a view model is that is designed to store all of the data for the view to which it corresponds.
Create an EnterValuesViewModel class and instantiate it with all of the necessary data from both of your business entities. Then type your view to this class.
public class EnterValuesViewModel
{
public string EnteredValue { get; set; }
public List<EmployeeDetailsViewModel> Employees { get; set; }
}
public class EmployeeDetailsViewModel
{
public string EmployeeId { get; set; }
public string ManagerId { get; set; }
}
View:
#model EnterValuesViewModel
#Html.TextBoxFor(m=>m.EnteredValue)
#foreach(EmployeeDetailsViewModel emp in Model.Employees)
{
#* Stuff about each employee goes here *#
}
Alternatively, look at partial views.
Related
I am trying to submit a form with a model that has a nested class within it. However when I get the data to the controller, the nested class has null fields.
Model:
public class Person
{
public string Name { get; set; }
public ExtraStuff Stuff { get; set; } = new ExtraStuff();
}
public class ExtraStuff
{
public string Field1 { get; set; }
public string Field2 { get; set; }
}
View:
#model ProjectName.Models.Person
#Html.TextBoxFor(model => model.Name)
#Html.TextBoxFor(model => model.Stuff.Field1)
#Html.TextBoxFor(model => model.Stuff.Field2)
Controller:
public ActionResult ActionName (Person data)
{
data.Name //this is fine
data.Stuff.Field1 //comes in empty
data.Stuff.Field2 //comes in empty
}
I'm wondering if you're doing some custom form submission, because there doesn't seem to be anything wrong with the code provided. If you make a form like the following it should work:
#using (Html.BeginForm("ActionName", "MyController"))
{
#Html.TextBoxFor(model => model.TopValue)
#Html.TextBoxFor(model => model.Nested.SomeValue)
<input type="submit" value="Submit"/>
}
Take a look at this fiddle for example.
I have a simple mvc5 code first application, It has a ms SQL database in the back-end and and a form in the front-end.
While I insert into database via the front end form, it does not generate any error, everything seems OK but when i check the back end database table, then all values in the newly inserted row are showing as NULL.
This is my code for model:
public class students
{
public int Id { get; set; }
[Display(Name = "Name")]
public string st_name { get; set; }
[Display(Name = "Father's Name")]
public string st_father_name { get; set; }
public string st_contact { get; set; }
}
This is the View Model class:
public class AddStudentViewModel
{
public students stdntss { get; set; }
}
This is the controller:
public ActionResult Index()
{
var std = _context.stdnts;
if (std==null)
{
return Content("Nothing Found");
}
return View(std);
}
public ActionResult AddStudent()
{
return View();
}
[HttpPost]
public ActionResult Insert(students st)
{
_context.stdnts.Add(st);
_context.SaveChanges();
return RedirectToAction("Index","Students");
}
And finally this is the view:
#model school2.ViewModels.AddStudentViewModel
#{
ViewBag.Title = "AddStudent";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>New student's registration form</h2>
#using (Html.BeginForm("Insert","Students"))
{
<div class="form-group">
#Html.LabelFor(m=> m.stdntss.st_name)
#Html.TextBoxFor(m=> m.stdntss.st_name, new { #class="form-control"})
</div>
<div class="form-group">
#Html.LabelFor(m => m.stdntss.st_father_name)
#Html.TextBoxFor(m => m.stdntss.st_father_name, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.stdntss.st_contact)
#Html.TextBoxFor(m => m.stdntss.st_contact, new { #class = "form-control" })
</div>
<button type="submit" class="btn btn-primary">Save</button>
}
Kindly assist me if anyone has any clue?
One way to solve this is to change the POST method to accept the same model as the view.
try changing
public ActionResult Insert(students st)
{
_context.stdnts.Add(st);
_context.SaveChanges();
return RedirectToAction("Index","Students");
}
to
public ActionResult Insert(AddStudentViewModel st)
{
_context.stdnts.Add(st.stdntss );
_context.SaveChanges();
return RedirectToAction("Index","Students");
}
or changing the model of the form to simply be student.
I think that change #Html.TextBoxFor(model=> model.stdntss.st_name, new { #class="form-control"}). because call Model, #model school2.ViewModels.AddStudentViewModel . Variable default Model.
I have been trying to get two models to appear in a single view using ViewModels but am failing.
I have simple view with 3 fields right now (Comment, Name, Department) and and a model to match it. I have a controller that returns an empty view and when you submit the form, the empty model is filled in and passed back to the controller. I now want to turn the department field into a drop down and have deduced (maybe incorrectly?) that I should create another model with the static values in it and then pass the ViewModel to the view via the controller but when I attempt to do this, it fails:
View:
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="fieldset">
<fieldset>
<legend>CommentDb</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Comment)
</div>
<div>
#Html.TextAreaFor(model => model.Comment, new {style = "width: 900px; height:200px;", autocomplete = "off" })
#Html.ValidationMessageFor(model => model.Comment)
</div>
<div class="editor-label">
#Html.Label("Your Name")
#*#Html.LabelFor(model => model.CommentByName)*#
#Html.TextBoxFor(model => model.CommentByName, new { autocomplete = "off", placeholder = "Optional" } )
#Html.ValidationMessageFor(model => model.CommentByName)
</div>
<div class="editor-label">
#Html.Label("Your Department", new { #class = "display-label" })
#*#Html.LabelFor(model => model.Department)*#
#Html.TextBoxFor(model => model.Department, new { autocomplete = "off", placeholder = "Optional" })
#Html.ValidationMessageFor(model => model.Department)
</div>
</fieldset>
<br />
<br />
</div>
<div>
<input type="submit" value="Create" id="submit"/>
</div>
}
Department drop down model:
namespace SuggestionBox.Models
{
public class DropDownModel
{
public String Departments { get; set; }
public String SetDropDownList()
{
Departments = "Engineering";
return Departments;
}
}
}
Database model:
namespace SuggestionBox.Models
{
public class CommentModel
{
[Key]
public int CommentiD { get; set; }
public string CommentByName { get; set; }
public string Department { get; set; }
[Required]
public string Comment { get; set; }
public DateTime InsertDate { get; set; }
}
}
namespace SuggestionBox.Models
{
public class CommentDbContext : DbContext
{
public CommentDbContext() : base()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<CommentDbContext, SuggestionBox.Migrations.Configuration>());
}
public DbSet<CommentModel> Comments { get; set; }
}
}
My attempted ViewModel:
namespace SuggestionBox.ViewModels
{
public class SuggestionBoxViewModel
{
public CommentModel Comments { get; set; }
public DropDownModel Departments { get; set; }
public SuggestionBoxViewModel()
{
Departments = new DropDownModel();
Departments.SetDropDownList();
Comments = new CommentModel();
}
}
}
The Controller:
public ViewResult Index()
{
SuggestionBoxViewModel vm = new SuggestionBoxViewModel();
return View(vm);
}
In return View(vm);, the IDE says: Arguement type 'SuggestionBox.ViewModels.SuggestionBoxViewModel' is not assignable to the model type 'SuggestionBox.Models.CommentModel'
Any idea what I am doing wrong here?
Cheers.
You are making a simple task into something overly complex. Your view model should contain only the properties used in the view, and should not contain methods. Populating your view model properties is the responsibility of the controller.
View model
public class CommentModelVM
{
[Required]
public string Comment { get; set; }
public string CommentByName { get; set; }
[Display(Name="Your Department")] // add attributes associated with the view
public string Department { get; set; }
public SelectList DepartmentList { get; set } // to populate the dropdown options
}
Controller
public ActionResult Create()
{
CommentModelVM model = new CommentModelVM();
ConfigureViewModel(model);
return View(model);
}
public ActionResult Create(CommentModelVM model)
{
if (!ModelState.IsValid())
{
// Repopulate options and return view
ConfigureViewModel(model);
return View(model);
}
// Save and redirect
}
private void ConfigureViewModel(CommentModelVM model)
{
List<string> departments = // create your list of departments here (from database or static list)
model.DepartmentList = new SelectList(departments);
}
View
....
#Html.LabelFor(m => m.Department)
#Html.DropDownListFor(m => m.Department, Model.DepartmentList)
....
I just want to start by saying that generally it is a bad idea to name properties or classes for our ViewModels out the view controls that they are bound to. For example: DropDownModel. Doing this creates confusion since Models and ViewModels don't represent a UI component they represent entities and data that the view uses to render its UI controls.
With that being said to answer you question I don't see the need for a ViewModel class to represent the static list of departments for your dropdown. I think you should just add a new list of departments to your SuggestionBoxViewModel class like this:
namespace SuggestionBox.ViewModels
{
public class SuggestionBoxViewModel
{
public CommentModel Comments { get; set; }
public IEnumerable<string> Departments { get; set; }
public string SelectedDepartment { get; set; }
public SuggestionBoxViewModel()
{
Departments = new [] {"Engineering","Sales"};
Comments = new CommentModel();
}
public int CommentiD
{
get { return Comments.CommentiD; }
}
public string CommentByName
{
get { return Comments.CommentByName; }
}
}
}
Then in your view all you have to do is bind the dropdown to the list of departments. Like this:
At the top of your view:
#model SuggestionBox.ViewModels.SuggestionBoxViewModel
Then where you want the dropdown to display:
#Html.DropDownListFor(m => m.SelectedDepartment, new SelectList(Model.Departments))
And that's it! I hope this helps.
Your View seems to expect a Comment Model.
If you wanted to bind to a ViewModel, then you would have to implement all the properties that Comment exposes.
So your ViewModel might look like this:
namespace SuggestionBox.ViewModels
{
public class SuggestionBoxViewModel
{
public CommentModel Comments { get; set; }
public DropDownModel Departments { get; set; }
public SuggestionBoxViewModel()
{
Departments = new DropDownModel();
Departments.SetDropDownList();
Comments = new CommentModel();
}
public int CommentiD
{
get { return Comments.CommentiD; }
}
public string CommentByName
{
get { return Comments.CommentByName; }
}
...etc.
}
}
Within my MainView, I was able to render all the "TaskComment"(model) using _GetForTask partial view. Then within my _GetForTask partial view, I was able to render _TaskCommentForm and successfull passed a new instance of TaskComment model. However, whenever I click the "Submit" button in the _TaskCommentForm partial view, it always returns null. What am I missing here? Thanks a lot.
"TaskComment" model
public partial class TaskComment
{
public int TaskCommentID { get; set; }
public Nullable<int> TaskID { get; set; }
public Nullable<int> AuthorID { get; set; }
public string Comment { get; set; }
public Nullable<System.DateTime> TimeStamp { get; set; }
public virtual Task Task { get; set; }
public virtual Employee Employee { get; set; }
}
Here's my "MainView"
#Html.Action("_GetForTask", "TaskComment", new { TaskID = Model.TaskID })
_GetForTask PartialView
#model IEnumerable<ProjectYesha.Models.TaskComment>
<div id="comments">
<ul>
#foreach (var taskComment in Model)
{
<li>#taskComment.Comment</li>
}
</ul>
#using (Html.BeginForm("_Submit", "TaskComment", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.Action("_TaskCommentForm", "TaskComment", new { TaskID = ViewBag.TaskID })
}
</div>
_TaskCommentForm PartialView
#model ProjectYesha.Models.TaskComment
#Html.HiddenFor(m=> m.TaskCommentID)
#Html.HiddenFor(m=> m.TaskID)
#Html.HiddenFor(m=> m.AuthorID)
#Html.HiddenFor(m=> m.TimeStamp)
#Html.HiddenFor(m=> m.Employee)
#Html.HiddenFor(m=> m.Task)
<div>
#using (Html.BeginForm())
{
#Html.EditorFor(m => m.TaskID)
#Html.EditorFor(m => m.Comment)
<input type="submit" value = "Submit" />
}
</div>
TaskCommentController
public PartialViewResult _GetForTask(Int32 taskID)
{
ViewBag.TaskID = taskID;
List<TaskComment> comments = db.TaskComments.Where(c => c.TaskID == taskID).ToList();
return PartialView("_GetForTask", comments);
}
[ChildActionOnly()]
public PartialViewResult _TaskCommentForm(Int32 taskID)
{
TaskComment comment = new TaskComment()
{
TaskID = taskID ,
};
return PartialView("_TaskCommentForm", comment);
}
[HttpPost]
[ValidateAntiForgeryToken()]
public PartialViewResult _Submit(TaskComment comment)
{
db.TaskComments.Add(comment);
db.SaveChanges();
List<TaskComment> comments = db.TaskComments.Where(c => c.TaskID == comment.TaskID).ToList();
ViewBag.TaskID = comment.TaskID;
return PartialView("_GetForTask", comments);
}
I have XML file which contains my data and I want from dropdownlist save choose string to this xml.
In my view I have this:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>MatchXML</legend>
...
<div class="editor-label">
#Html.LabelFor(model => model.Team)
</div>
<div class="editor-field">
#Html.DropDownList("Team", (SelectList)ViewBag.Team, String.Empty)
#Html.ValidationMessageFor(model => model.Team)
</div>
...
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
In controller:
public ActionResult Pridat()
{
ViewBag.Team = new SelectList(repo.GetTeams(), "Name", "Name");
return View();
}
[HttpPost]
public ActionResult Pridat(MatchXML match, string Team)
{
if (ModelState.IsValid)
{
try
{
ViewBag.Team = new SelectList(repo.GetTeams(), "Name", "Name");
match.Team = repo.GetTeamByName(Team);
repo.AddMatch(match);
return RedirectToAction("Index");
}
catch (Exception ex)
{
//error msg for failed insert in XML file
ModelState.AddModelError("", "Error creating record. " + ex.Message);
}
}
return View(match);
}
Models looks:
public class MatchXML
{
public int MatchXMLID { get; set; }
public string Opponent { get; set; }
public DateTime MatchDate { get; set; }
public string Result { get; set; }
public Team Team { get; set; }
public int Round { get; set; }
}
public class Team
{
public int TeamID { get; set; }
public string Name { get; set; }
public virtual User Coach { get; set; }
public virtual ICollection<Player> Players { get; set; }
}
I was trying do some modification to do this but it is not working. I can do it with TeamID and saving ID but I want in xml save string (name of team). Thanks for help
Edit:
I updated show code of controller and view method.
You are binding the dropdown to the Team complex property (first argument of the DropDownList helper). This doesn't make sense. You can bind only to scalar values. I would also recommend you using the strongly typed version of the helper:
#Html.DropDownListFor(x => x.Team.TeamID, (SelectList)ViewBag.Team, String.Empty)
This way you will populate the TeamID property in the POST action with the selected value from the dropdown.
Also replace:
#Html.ValidationMessageFor(model => model.Team)
with:
#Html.ValidationMessageFor(model => model.Team.TeamID)