MVC dropdownlist wrong display - c#

I am maing an MVC application connected to Entity Framework. In my view I have a dropdown list. Code looks like this:
#{
ViewBag.Title = "ClassesPickGroup"; } #model ClassDeclarationsThsesis.Models.ClassesPickGroupViewModel
<h2>ClassesPickGroup</h2>
#foreach (var user in Model.users) {
if (user.email.Replace(" ", String.Empty) == HttpContext.Current.User.Identity.Name)
{
if (user.user_type.Replace(" ", String.Empty) == 3.ToString() || user.user_type.Replace(" ", String.Empty) == 2.ToString())
{
using (Html.BeginForm("ClassesPickGroup", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Generate summary views</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#{
List<SelectListItem> listItems1 = new List<SelectListItem>();
foreach (var sub in Model.subjects)
{
if (sub.name.Replace(" ", String.Empty) == Model.subject_name.Replace(" ", String.Empty))
{
Model.subject_id = sub.class_id;
}
}
foreach (var group in Model.groups)
{
if (group.class_id == Model.subject_id)
{
listItems1.Add(new SelectListItem
{
Text = group.name,
Value = group.name,
});
}
}
}
#Html.LabelFor(m => m.selected_group, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.selected_group, listItems1, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Submit" />
</div>
</div>
}
}
if (user.user_type.Replace(" ", String.Empty) == 1.ToString())
{
<p>You do not have enough permissions to enter this page. Contact the administrator.</p>
}
}
}
However, in my dropdown list I see wrong things. The number of elements is correct, but all the names are the same, all the names correspond to first matching 'group' to pick from model. What do I do wrong?
My controller looks like this:
public ActionResult ClassesPickGroup(ClassesPickGroupViewModel value)
{
ClassDeclarationsDBEntities1 entities=new ClassDeclarationsDBEntities1();
int subj_id=0;
ClassesPickGroupViewModel model=new ClassesPickGroupViewModel();
model.subject_name = value.subject_name;
foreach (var subject in entities.Subjects)
{
if(subject.name.Replace(" ",String.Empty)==value.subject_name.Replace(" ", String.Empty))
{
subj_id = subject.class_id;
}
}
model.groups = entities.Groups.ToList();
model.subjects = entities.Subjects.ToList();
model.users = entities.Users.ToList();
if (ModelState.IsValid)
{
return RedirectToAction("ClassesView", "Account");
}
else
{
model.groups = entities.Groups.ToList();
model.subjects = entities.Subjects.ToList();
model.users = entities.Users.ToList();
return View(model);
}
return View(model);
}
Apparently, adding groups does not work well, groups are not unique (however in database they are). What is wrong with it?

You are not passing any value for model.subject_id from controller. That is why the last value is kept saved for taking names it only hits the same subject_id
#{
ViewBag.Title = "ClassesPickGroup"; } #model ClassDeclarationsThsesis.Models.ClassesPickGroupViewModel
<h2>ClassesPickGroup</h2>
#foreach (var user in Model.users) {
if (user.email.Replace(" ", String.Empty) == HttpContext.Current.User.Identity.Name)
{
if (user.user_type.Replace(" ", String.Empty) == 3.ToString() || user.user_type.Replace(" ", String.Empty) == 2.ToString())
{
using (Html.BeginForm("ClassesPickGroup", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Generate summary views</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#{
List<SelectListItem> listItems1 = new List<SelectListItem>();
foreach (var sub in Model.subjects)
{
if (sub.name.Replace(" ", String.Empty) == Model.subject_name.Replace(" ", String.Empty))
{
Model.subject_id = sub.class_id;
}
foreach (var group in Model.groups)
{
if (group.class_id == Model.subject_id)
{
listItems1.Add(new SelectListItem
{
Text = group.name,
Value = group.name,
});
}
}
}
}
}
#Html.LabelFor(m => m.selected_group, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.selected_group, listItems1, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Submit" />
</div>
</div>
}
}
if (user.user_type.Replace(" ", String.Empty) == 1.ToString())
{
<p>You do not have enough permissions to enter this page. Contact the administrator.</p>
}
}
}

Related

bind another model to partial view like nested partial view binding

I have a button which add individualSearch partial view and individualSearch partial view also have a add button which adds individualSearcharacteristic partial view in it.
I want to bind BMRTestData model with individualSearch partial so that i can get the characteristic partial view data. So i store that data in IndividualSearch's list public List<Characteristic> Characteristics { get; set; } = new List<Characteristic>();
Please guide me to do same as i am new to .net .
Coding
//TestData(Main View)
#using ABC.Core.Models.DTOs
#model ABC.Core.Models.Api.BMRTestData
#using (Html.BeginForm())
{
<div class="card mb-3">
<h5 class="card-header">Response</h5>
<div class="card-body">
<div class="card-block">
<div class="form-group">
#Html.LabelFor(m => m.CompanyName, "Company Name", new { #class = "form-control-label" })
#Html.TextBoxFor(m => m.CompanyName, null, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.CompanyName)
</div>
<div id="searchindividuals" class="mb-3">
#if (Model?.IndividualSearches != null)
{
for (var i = 0; i < Model?.IndividualSearches.Count; i++)
{
<div class="form-group">
#{ Html.RenderPartial("IndividualSearchPartial", Model.IndividualSearches[i], new ViewDataDictionary()); }
</div>
}
}
</div>
<div class="mb-3">
<button id="add-search-individual" type="button" class="btn btn-success">Add Search Individual</button>
</div>
<button id="add-company-characteristic" type="button" class="btn btn-success">Add Characteristic</button>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
}
#section Scripts
{
function add(element){
var action = ' #Url.Action("NewIndividualSearchCharacteristic", "Blended")';
$.post(action)
.done(function (partialView) {
$(element.previousElementSibling).append(partialView);
});
}
</script>
}
//IndividualSearchPartial
#using (Html.BeginCollectionItem("IndividualSearches"))
{
<div id="individual-details" class="card">
<div class="form-horizontal">
<div class="card-block">
<div class="form-group">
#Html.LabelFor(m => m.SearchPostcode, "Search Post Code", new { #class = "form-control-label" })
#Html.TextBoxFor(m => m.SearchPostcode, null, new { #class = "form-control" })
</div>
</div>
</div>
<div class="card-block">
<div id="Characteristics" class="mb-3">
#if (Model?.Characteristics != null)
{
for (var i = 0; i < Model?.Characteristics.Count; i++)
{
<div class="form-group">
#{ Html.RenderPartial("IndividualSearchCharacterisiticPartial", Model.Characteristics[i], new ViewDataDictionary()); }
#* #Html.EditorFor(m => m.Characteristics);*#
</div>
}
}
</div>
<button id="add-characteristics" onclick="add(this)" type="button" class="btn btn-success">Add Characteristics</button>
</div>
</div>
}
// IndividualSearchCharacterisiticPartial
#model ABC.Core.Models.DTOs.Characteristic
#using (Html.BeginCollectionItem("Characteristics"))
{
<div id="characteristic-details" class="card">
<div class="form-horizontal">
<div class="card-block">
<div class="container">
<div class="row">
<div class="col-*-*">
#Html.LabelFor(m => m.Name, "Name", new { #class = "form-control-label" })
</div>
<div class="col">
#Html.TextBoxFor(m => m.Name, null, new { #class = "form-control" })
</div>
<div class="col-*-*">
#Html.LabelFor(m => m.Value, "Value", new { #class = "form-control-label" })
</div>
<div class="col">
#Html.TextBoxFor(m => m.Value, null, new { #class = "form-control" })
</div>
<div class="col-*-*">
<a id="characteristic-remove" href="#" onclick="removeCharacteristic(this)" class="btn btn-danger pull-right">Remove</a>
</div>
</div>
</div>
</div>
</div>
</div>
}
//IndividualSearch Class
namespace ABC.Core.Models.DTOs.Individual
{
public class IndividualSearch
{
public List<Characteristic> Characteristics { get; set; } = new List<Characteristic>();
}
}
namespace ABC.Core.Models.Api
{
public class BMRTestData : BMRRequest
{
public List<IndividualSearch> IndividualSearches { get; set; } = new List<IndividualSearch>();
}
}
Update
You can add onclick event in Add Search Individual button:
<button id="add-search-individual" type="button" class="btn btn-success" onclick="addSearch(this)">Add Search Individual</button>
Add an action in controller to return IndividualSearchPartial partial view:
[HttpPost]
public ActionResult IndividualSearchCharacteristic()
{
IndividualSearch individualSearch = new IndividualSearch() { };
return PartialView("IndividualSearchPartial", individualSearch);
}
Here is all the js in main view:
#section Scripts
{
<script>
function add(element){
var action = ' #Url.Action("NewIndividualSearchCharacteristic", "Default")';
$.post(action)
.done(function (partialView) {
$(element).parents('#individual-details').find("#Characteristics").append('<div class="form-group">' + partialView + '</div>');
ResetName();
});
}
function addSearch(element){
var action = ' #Url.Action("IndividualSearchCharacteristic", "Default")';
$.post(action)
.done(function (partialView) {
$(element).parents('.mb-3').find('#searchindividuals').append('<div class="form-group search">' + partialView + '</div>');
ResetName();
});
}
function ResetName() {
var index = 0;
$(".search").each(function () {
var nameIndex = 0; var valueIndex = 0;
$(this).find(":input[type='hidden']").each(function () {
$(this).removeAttr("name");
});
$(this).find(":input[type='text']").each(function () {
if ($(this).attr("name").indexOf("Characteristics") > -1 && $(this).attr("name").indexOf("Name") > -1) {
$(this).attr("name", "IndividualSearches[" + index + "].Characteristics[" + nameIndex + "].Name");
nameIndex++;
return;
}
if ($(this).attr("name").indexOf("Characteristics") > -1 && $(this).attr("name").indexOf("Value") > -1) {
$(this).attr("name", "IndividualSearches[" + index + "].Characteristics[" + valueIndex + "].Value");
valueIndex++;
return ;
}
if ($(this).attr("name").indexOf("IndividualSearches") > -1) {
$(this).attr("name", "IndividualSearches[" + index + "].SearchPostcode");
return;
}
});
index++;
})
}
</script>
}
After submit, it will enter into following action to receive BMRTestData data:
[HttpPost]
public IActionResult TestData(BMRTestData bMRTest)
{
return View();
}
Here is the test result:

my search button goes to the wrong function

My Get function works fine and the search textbox shows but when I enter the user ID and click search, it goes directly to the post function. It is supposed to go to the Get function again to show the data . after the data shows and whether I selected from the checkboxes or not, I click save and then it is supposed to go to the POst function.
What am I doing wrong?
GET function :
[HttpGet]
public ActionResult Index(int? SearchId)
{
var viewModel = new UserViewModel();
if (SearchId != null)
{
var userDepartments = db.TBL_User_Dep_Access.Where(x => x.UserID == SearchId).Select(x => x.Dep_ID).ToList();
List<UserDepartmentViewModel> udeptVM = db.TBL_Department.Select(i => new UserDepartmentViewModel
{
Dep_Id = i.Department_ID,
Dep_Name = i.Department_Name,
IsChecked_ = userDepartments.Contains(i.Department_ID)
}).ToList();
var userPermissions = db.TBL_UserPermissions.Where(x => x.UserID == SearchId).Select(m => m.PermissionID).ToList();
List<UsrPERViewModel> upVM = db.TBL_Permissions.Select(i => new UsrPERViewModel
{
Id = i.PermissionID,
Name = i.PermissionName,
IsChecked = userPermissions.Contains(i.PermissionID)
}).ToList();
viewModel.Departments = udeptVM;
viewModel.Permissions = upVM;
}
return View(viewModel);
}
My View:
#model Staff_Requisition.Models.UserViewModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<style>
.list-group {
max-height: 300px;
margin-bottom: 10px;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
</style>
#using (Html.BeginForm("Index", "TBL_UserPermission"))
{
#Html.AntiForgeryToken()
<body class="nav-md">
<div class="container body">
<div class="main_container">
<div class="title_right">
<div class="col-md-5 col-sm-5 col-xs-12 form-group pull-right top_search">
<div class="input-group">
#Html.TextBox("SearchId", "", null, new { #id = "SearchId", #placeholder = "Search for...", #class = "form-control" })
<span class="input-group-btn">
<input class="btn btn-default" value="Search" type="submit">Go! />
</span>
<ul>
#if (Model.Permissions != null)
{
foreach (var P in Model.Permissions)
{
<li>
<p>
#Html.CheckBoxFor(modelItem => P.IsChecked, new { #class = "flat", #value = P.IsChecked })
#Html.DisplayFor(modelItem => P.Name, new { #class = "DepartmentName", #value = P.Name })
#Html.HiddenFor(modelItem => P.Id, new { #class = "Dep_Id", #value = P.Id })
</p>
</li>
}
}
</ul>
<ul class="to_do">
#if (Model.Departments != null)
{
foreach (var D in Model.Departments)
{
<li>
<p>
#Html.CheckBoxFor(modelItem => D.IsChecked_, new { #class = "flat", #value = D.IsChecked_ })
#Html.DisplayFor(modelItem => D.Dep_Name, new { #class = "DepartmentName", #value = D.Dep_Name })
#Html.HiddenFor(modelItem => D.Dep_Id, new { #class = "Dep_Id", #value = D.Dep_Id })
</p>
</li>
}
}
</ul>
<div class="col-xs-12 col-sm-6 emphasis">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</body>
}
My POST function:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(UserViewModel user_Pers)
{
//remove user with specified ID from database
db.TBL_UserPermissions.RemoveRange(db.TBL_UserPermissions.Where(c => c.UserID == user_Pers.SearchId));
db.TBL_User_Dep_Access.RemoveRange(db.TBL_User_Dep_Access.Where(c => c.UserID == user_Pers.SearchId));
//for each permission that's checked add user to the table
foreach (var u in user_Pers.Permissions)
{
if (u.IsChecked)
{
TBL_UserPermissions Tup = new TBL_UserPermissions();
Tup.UserID = user_Pers.SearchId;
Tup.PermissionID = u.Id;
Tup.IsActive = true;
db.TBL_UserPermissions.Add(Tup);
}
}
db.SaveChanges();
foreach (var d in user_Pers.Departments)
{
if (d.IsChecked_)
{
TBL_User_Dep_Access Tud = new TBL_User_Dep_Access();
Tud.UserID = user_Pers.SearchId;
Tud.Dep_ID = d.Dep_Id;
Tud.IsActive = true;
db.TBL_User_Dep_Access.Add(Tud);
}
}
db.SaveChanges();
return RedirectToAction("myInfo");
}
BTW I removed most of the div in the view manually for simplicity, so it's okay if an opening or closing doesn't match.
As has been pointed out in the comments, in your code you have 1 form whereas to solve the problem you are talking about you need 2 forms. One form responsible for the search get request and the other responsible for the user post.
Here is a simple example of a search form and an update form on the same page.
The viewmodel and controller
using System.Web.Mvc;
namespace SearchAndSubmit.Controllers
{
public class UserViewModel
{
public int? Id { get; set; }
public string Name { get; set; }
}
public class HomeController : Controller
{
[HttpGet]
public ActionResult Edit(int? SearchId)
{
var viewModel = new UserViewModel();
if (SearchId != null)
{
viewModel.Id = SearchId;
//logic to search for user and create viewmodel goes here
}
return View(viewModel);
}
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Edit(UserViewModel user_Pers)
{
//validation and create update logic goes here
return RedirectToAction("Index");
}
}
}
The view
#model SearchAndSubmit.Controllers.UserViewModel
#{
ViewBag.Title = "Edit/create user";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>#ViewBag.Title</h2>
#*This is the search form it does a get request*#
#using (Html.BeginForm("edit", "home", FormMethod.Get))
{
#Html.TextBox("SearchId", "", null, new { #id = "SearchId", #placeholder = "Search for...", #class = "form-control" })
<span>
<input value="Search" type="submit">
</span>
}
#*This is the form for updating the user it does a post*#
#using (Html.BeginForm("edit", "home", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(c => c.Id)
<p>
#Html.LabelFor(c => c.Name)
#Html.TextBoxFor(c => c.Name)
</p>
<div>
<input type="submit" value="Save" />
</div>
}

asp.NET mvc, get model list values from view

I am new to mvc and am trying to do something like in the below image (im not using partial views).
I have an IEnumerable property on Model
Like in this image, (i have not enough reputation to show image directly)
but on controller if i put FormCollection as parameter to accepting post method when i process same name fields i get an extra character ',', which might be also used by user...
Any idea....
[EDIT]
My view
#model Models.Question
#{
ViewBag.Title = "Add";
}
<h2>Add</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Question</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.SurveyId)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.QuestionTypeId, "Question type", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.QuestionTypeId, new SelectList(ViewBag.QuestionTypes, "QuestionTypeId", "Name"), new { #class = "form-control col-md-10" })
<button type="button" class="btn btn-default addAnswer hide"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
#Html.ValidationMessageFor(model => model.QuestionTypeId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group hide">
#Html.LabelFor(model => model.Answers, "Options", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10" id="allAnswers">
#Html.ValidationMessageFor(model => model.Answers, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Sort, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Sort, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Sort, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Mandatory, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Mandatory)
#Html.ValidationMessageFor(model => model.Mandatory, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Question", "Survey", new { id = Model.SurveyId }, null)
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval", "~/Scripts/QuestionAdd.js")
}
Controller
[HttpGet]
public ActionResult Add(long id)
{
var question = new Models.Question();
question.SurveyId = id;
ViewBag.QuestionTypes = BLL.Questions.GetQuestionTypes();
return View(question);
}
[HttpPost]
public ActionResult Add(FormCollection coll)
{
if (ModelState.IsValid)
{
var question = new Models.Question();
question.Name = coll["Name"];
byte qid = 0, sort = 0;
bool mandatory = false;
byte.TryParse(coll["QuestionTypeId"], out qid);
byte.TryParse(coll["Sort"], out sort);
bool.TryParse(coll["Mandatory"], out mandatory);
question.QuestionTypeId = qid;
question.Sort = sort;
question.Mandatory = mandatory;
foreach (var answer in coll["Answers"])
question.Answers.Add(new Models.Answer() { Value = answer + "" });
if (question != null)
{
if (BLL.Questions.Insert(question) != null)
ViewBag.Message = "Successfully inserted";
else
ViewBag.Message = "Insert could not be done";
return RedirectToAction("Index", "Question", new { questionId = question.QuestionId });
}
}
return View();
}
When (+) clicked
$('#allAnswers').append(
'<div class="input-group col-lg-4">' +
'<input class="form-control" name="Answers"> ' +
'<div class="input-group-btn">' +
' <button type="button" class="btn btn-default removeAnswer"><span class="glyphicon glyphicon glyphicon-trash" aria-hidden="true"></span></button>' +
'</div> </div>');
As discussed.. here is how i would approach this.
I have a view model to hold the questions and answers and the selected question to which we will be adding answers.
public class CurrentViewModel
{
public string QuestionSelected { get; set; }
public List<SelectListItem> Questions { get; set; }
public List<string> Answers { get; set; }
}
Then in your controller we have an action to return the view, an action to get the answers for the selected question, an action to add a new answer for the selected question and also a save method which just demonstrates the final model content posted.
public class TestController : Controller
{
public ActionResult Test()
{
var model = new CurrentViewModel()
{
Questions = new List<SelectListItem>()
{
new SelectListItem()
{
Text = "Question 1",
Value = "Question 1"
},
new SelectListItem()
{
Text = "Question 2",
Value = "Question 2"
}
},
Answers = new List<string>()
};
return View("Test", model);
}
public PartialViewResult GetAnswers(CurrentViewModel model)
{
model.Answers = new List<string>();
//model.Answers = Get Answers from some service based on QuestionSelected?!
model.Answers.Add("Answer 1");
model.Answers.Add("Answer 2"); //Add manuall for example
return PartialView("_Answers", model);
}
public PartialViewResult AddAnswer(CurrentViewModel model)
{
model.Answers.Add("Add answer here...");
return PartialView("_Answers", model);
}
public ActionResult SaveQuestionsAndAnswers(CurrentViewModel model)
{
if (model.Questions.Count == 0)
{
}
return View("Test", model);
}
}
Then we have a main view for showing the questions dropdown and a partial view that will show us the answers.
Main View
#model TestMVC.Models.CurrentViewModel
#{
ViewBag.Title = "Test";
}
<link href="~/Content/StyleSheets/jquery-ui.css" rel="stylesheet" />
<script src="~/Content/Scripts/jquery-2.2.3.js"></script>
<script src="~/Content/Scripts/jquery-ui-1.11.4.js"></script>
<div id="divBodyContent">
<div>
<h3>Q & A</h3>
</div>
#using (Html.BeginForm("SaveQuestionsAndAnswers", "Test", FormMethod.Post, new { id = "frmQandA" }))
{
#Html.Label("lblQ", "Questions", new { #class = "form-control inline" })
#Html.DropDownListFor(model => model.QuestionSelected, Model.Questions, "Select--", new { #class = "form-control inline", id="ddQuestions" })
<div id="divAnswers">
#Html.Partial("_Answers")
</div>
<div style="margin-top: 1%;">
<button id="btnSave" type="submit" class="btn btn-primary" style="margin-left: 4px; margin-bottom: 10px; width: 7%">save</button>
</div>
}
</div>
<script>
$("#ddQuestions").on("change", function() {
var myData = $('#frmQandA').serialize();
$.ajax({
type: "POST",
url: "#Url.Action("GetAnswers", "Test")",
data: myData,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: function(data) {
$("#divAnswers").html(data);
}
})});
</script>
Partial View
#model TestMVC.Models.CurrentViewModel
<link href="~/Content/StyleSheets/jquery-ui.css" rel="stylesheet" />
<script src="~/Content/Scripts/jquery-2.2.3.js"></script>
<script src="~/Content/Scripts/jquery-ui-1.11.4.js"></script>
<div>
#for (var counter = 0; counter <= (Model.Answers.Count - 1); counter++)
{
#Html.TextBoxFor(model => model.Answers[counter], new {#class = "form-control inline"})
}
<div style="margin-top: 1%;">
<button id="btnAddAnswer" type="button" class="btn btn-primary" style="margin-left: 4px; margin-bottom: 10px; width: 7%">Add</button>
</div>
</div>
<script>
$("#btnAddAnswer").on("click", function() {
var myData = $('#frmQandA').serialize();
$.ajax({
type: "POST",
url: "#Url.Action("AddAnswer", "Test")",
data: myData,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
success: function (data) {
$("#divAnswers").html(data);
}
})});
</script>
I've tested this locally and it works. In a nutshell, when we need a new answer adding to the model, we add it in server side so we can then bind to the model in the browser. We do this via an Ajax call on the change event of the questions drop down. The partial view iterates through each answer via a counter which generates a unique id and textbox for each answer. Adding a new answer is also achieved via ajax. These can then all be posted back.
Hope that helps.

Pass data between several views in MVC applications

I am creating a MVC application and I would like to pass data between views.
Here is my first view:
#model ClassDeclarationsThsesis.Models.AddGroupViewModel
#{
ViewBag.Title = "Add Groups";
}
<h2>Add Groups to subjects</h2>
#foreach (var user in Model.Users)
{
if (user.email.Replace(" ", String.Empty) == HttpContext.Current.User.Identity.Name)
{
if (user.user_type.Replace(" ", String.Empty) == 3.ToString() || user.user_type.Replace(" ", String.Empty) == 2.ToString())
{
using (Html.BeginForm("AddGroup", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Create new groups.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#{
List<SelectListItem> listItems1 = new List<SelectListItem>();
}
#foreach (var subject in Model.Subjects)
{
listItems1.Add(new SelectListItem
{
Text = subject.name,
Value = subject.name,
Selected = true
});
}
#Html.LabelFor(m => m.subject_name, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.subject_name, listItems1, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.qty, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.qty, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Submit" />
</div>
</div>
}
}
if (user.user_type.Replace(" ", String.Empty) == 1.ToString())
{
<p>You do not have enough permissions to enter this page. Contact the administrator.</p>
}
}
}
And my controller for this:
public ActionResult AddGroup(AddGroupViewModel model)
{
var entities = new ClassDeclarationsDBEntities1();
var model1 = new AddGroupViewModel();
model1.Subjects = entities.Subjects.ToList();
model1.Users = entities.Users.ToList();
// set your other properties too?
if (ModelState.IsValid)
{
return RedirectToAction("AddGroupsQty", "Account");
}
return View(model1);
}
And what I would like to achieve is to pass chosen item from dropdown list and this qty variable to AddGroupsQty View. How do I do this? In my controller of AddGroupsQty i have just a simple return of view so far.
You can pass the values using querystring.
return RedirectToAction("AddGroupsQty", "Account",
new { qty=model.qty,subject=model.subject_name);
Assuming your AddGroupsQty have 2 parameters to accept the quantity and subject
public ActionResult AddGroupsQty(int qty,string subject)
{
// do something with the parameter
// to do : return something
}
This will make browser to issue a new GET request with the values in query string. If you do not prefer to do that, you can use a server side temporary persistence mecahnism like TempData
TempData["qty"]=model.qty;
TempData["subject"]= model.subject_name;
return RedirectToAction("AddGroupsQty", "Account");
And in your AddGroupsQty action,
public ActionResult AddGroupsQty()
{
int qty=0;
string subjectName=string.Empty;
if(TempData["qty"]!=null)
{
qty = Convert.ToInt32(TempData["qty"]);
}
if(TempData["subject"]!=null)
{
subjectName = TempData["subject"];
}
// Use this as needed
return View();
}
If you want to pass these values from the ADdGroupsQty action to it's view, you can use either a view model or ViewBag/ViewData.

Asp.net mvc provider hosted app-upload a file

I have a provider hosted app (asp.net MVC) and am trying to upload a file using a form but nothing works.ie the HttpPostedFileBase is always NULL.
Kindly assist.
Here the code I’m using,
#using (Html.BeginForm("Create", "StudentProgress", routeValues,FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="modal-body">
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.fk_level_register)
#Html.HiddenFor(model => model.date_modified)
#Html.HiddenFor(model => model.done_by)
<label for="file">Filename:</label>
<input type="file" name="upload" id="file" style="width:240px" />
<div class="form-group">
#Html.LabelFor(model => model.submission_deadline_date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.submission_deadline_date)
#Html.ValidationMessageFor(model => model.submission_deadline_date)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.period_covered, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.period_covered, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.period_covered)
</div>
</div>
}
Instead of using File property as string datatype you can use HttpPostFileBasedatatype
ClassModel:
public DateTime submission_deadline_date { get; set; }
public string period_covered { get; set; }
public HttpPostedFileBase File { get; set; }
public string fk_level_register { get; set; }
public DateTime date_modified { get; set; }
public string done_by { get; set; }
Controler:
[HttpPost]
public ActionResult Create(Period collection)
{
string fpath = "";
try
{
if (Request.Files.Count > 0)
{
try
{
HttpPostedFileBase file = collection.File;
string fname;
// want to check extension then use this method
//if (CheckExtension(file.ContentType.ToLower()))
//{
// Checking for Internet Explorer
string extension = System.IO.Path.GetExtension(file.FileName);
if (Request.Browser.Browser.ToUpper() == "IE" || Request.Browser.Browser.ToUpper() == "INTERNETEXPLORER")
{
string[] testfiles = file.FileName.Split(new char[] { '\\' });
fname = Guid.NewGuid() + extension; //+ testfiles[testfiles.Length - 1];
}
else
{
fname = Guid.NewGuid() + extension; //+ file.FileName;
}
// Get the complete folder path and store the file inside it.
fname = System.IO.Path.Combine(Server.MapPath("~/Content/"), fname);
file.SaveAs(fname);
return Content("Successfully Uploaded");
//}
}
catch (Exception ex)
{
return Content("Error occurred. Error details: " + ex.Message);
}
}
}
catch (Exception)
{
return Content(Response.StatusCode.ToString() + " Bad Requrest error." + fpath);
}
return Content("No files selected.");
}
public bool CheckExtension(string Ext)
{
if (Ext == "application/pdf")
{
return true;
}
else if (Ext == "text/plain")
{
return true;
}
else if (Ext == "application/msword")
{
return true;
}
else if (Ext == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
{
return true;
}
else
{
return false;
}
}
View: in view only small change you need to do
#using (Html.BeginForm("Create", "Home", null, FormMethod.Post, new { id = "formU", enctype = "multipart/form-data" })){
#Html.AntiForgeryToken()
<div class="modal-body">
<div class="form-horizontal">
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.fk_level_register)
#Html.HiddenFor(model => model.date_modified)
#Html.HiddenFor(model => model.done_by)
<label for="file">Filename:</label>
<input type="file" name="File" id="File" style="width:240px" />
#*#Html.EditorFor(model => model.File, new { htmlAttributes = new { #type="file", #class = "form-control", #placeholder = "File path" } })*#
<div class="form-group">
#Html.LabelFor(model => model.submission_deadline_date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.submission_deadline_date)
#Html.ValidationMessageFor(model => model.submission_deadline_date)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.period_covered, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.period_covered, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.period_covered)
</div>
</div>
<div class="form-group">
<input id="submit" type="submit" value="Submit" class="btn btn-success" />
</div>
</div>
</div>}
you can also download source code from git hub repository click here
Since you are using a provider hosted app, why not use this approach?
https://msdn.microsoft.com/en-us/library/office/dn904536.aspx

Categories