How to differentiate between selection and save in MVC post - c#

I have a form which has a DropDownList to select users and a form for user data. All controls are nested inside a form.
Cureently user DropDownList submits the form to notify about user selection to fetch appropriate data.
I want have a Button type(submit) which saves the data for the current user. Since both controls are in the same form and they both do submit, how can I differentiate if I am trying to select the user or saving the data in my action?
I have tried creating two forms as follows:
#model MyApp.Models.UserModel
#{
ViewBag.Title = "Profiles";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript" src="chosen.jquery.js"></script>
<script type="text/javascript" src="bootstrap-switch.js"></script>
<link rel="stylesheet" href="chosen.css" />
<link rel="stylesheet" href="bootstrap-switch.css" />
<style type="text/css">
.chosen-search{
display: none;
}
.form-group label{
margin-top: 10px;
}
.row{
margin-bottom: 20px;
}
th{
text-align: center;
}
</style>
<script type="text/javascript">
$(document).ready(function () {
$('#CurrentUserId').chosen({placeholder_text_single: "Select a user"});
$('#CurrentGroupId').chosen({placeholder_text_single: "Select a group"});
$('#CurrentRoleId').chosen({placeholder_text_single: "Select a role"});
$('#IsActive').bootstrapSwitch({
onColor: "success",
offColor: "danger",
onText: "ACTIVE",
offText: "PASSIVE",
animate: false,
handleWidth: 60
});
$('.authorizationCheckBox').bootstrapSwitch({
onColor: "success",
offColor: "danger",
onText: "Y",
offText: "N",
animate: false,
size: "mini"
});
});
</script>
#using (Html.BeginForm("Profile", "User"))
{
#Html.AntiForgeryToken()
<div class="row">
<div class="col-sm-3">
<div class="row">
<label class="control-label">Selected user :</label>
</div>
</div>
<div class="col-sm-9">
<div class="row">
#Html.DropDownListFor(x => x.CurrentUserId, new SelectList(Model.AllUsers, "Id", "Username"), "", new { #class = "form-control", onchange = #"this.form.submit();" })
</div>
</div>
</div>
}
#using (Html.BeginForm("SaveProfile", "User"))
{
if (!string.IsNullOrWhiteSpace(Model.CurrentUser))
{
<div class="row">
<div class="col-sm-3">
<div class="row">
#if (string.IsNullOrWhiteSpace(Model.UserImageUrl))
{
<img src="no-user.png" class="img-circle" alt="..." style="width: 35%; display: block; margin: auto;">
<button type="button" class="btn btn-primary" style="display: block; margin: auto; margin-top: 10px;">
<span class="glyphicon glyphicon-upload"></span> Upload avatar
</button>
}
else
{
<img src="#Model.UserImageUrl" class="img-circle" alt="..." style="width: 35%; display: block; margin: auto;">
<button type="button" class="btn btn-primary" style="display: block; margin: auto; margin-top: 10px;">
<span class="glyphicon glyphicon-retweet"></span> Change avatar
</button>
}
</div>
<div class="row">
<div class="input-group" style="margin: 0 auto;">
<div class="switch-button xlg showcase-switch-button">
#Html.CheckBoxFor(x => x.IsActive)
</div>
</div>
</div>
</div>
<div class="col-sm-9">
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">Username :</label>
<div class="col-sm-10">
<input id="CurrentUser" name="CurrentUser" class="form-control form-control-flat" value="#Model.CurrentUser" />
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">E-mail :</label>
<div class="col-sm-10">
<input id="EMail" name="EMail" class="form-control form-control-flat" value="#Model.EMail" />
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">Membership :</label>
<div class="col-sm-10">
#Html.DropDownListFor(x => x.CurrentGroupId, new SelectList(Model.AllGroups, "Id", "Name"), "", new { #class = "form-control" })
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<label class="control-label col-sm-2">Role :</label>
<div class="col-sm-10">
#Html.DropDownListFor(x => x.CurrentRoleId, new SelectList(Model.AllRoles, "Id", "Name"), "", new { #class = "form-control" })
</div>
</div>
</div>
</div>
</div>
<button id="btnSave" type="submit" class="btn btn-info" style="float: right; margin-right: 10px; margin-bottom: 40px;">
<span class="glyphicon glyphicon-trash"></span>Save changes
</button>
}
}
[HttpGet]
public ActionResult Profile()
{
return View(CreateInitialUserModel());
}
[HttpPost]
public ActionResult Profile(UserModel model)
{
model = GetUserModel(model.CurrentUserId.Value);
ModelState.Clear();
return View(model);
}
[HttpPost]
public ActionResult SaveProfile(UserModel model)
{
SaveModel(model)
return RedirectToAction("Profile");
}
But the problem is, at HttpPost of Profile action works well. But when I click the Save button and the HttpPost SaveProfile action is called, input parameter model does not have the values set on the screen.

I would actually use two forms. Not only does it relieve your problem here, as you can just add a hidden field or something to each form to indicate which was submitted, but it prevents other issues you're likely to run into, like failing validation on any required user fields in the create form, when you just select a user, because no data was submitted for those fields.
Short of that, just use whatever JavaScript you're already using to automatically submit when an option is selected from the drop down to change a value of a hidden field or otherwise modify the post data before it's submitted.

Why not use jquery for data retrieval? You could switch you dropdown to instead call a jquery function that performs an ajax call to a controller method that retrieves the relevant user data. Then, you can bind the data to the appropriate fields on the page using jquery. You would then only have one submit button on your view, handled through the normal mvc form process.

-in drop downdown list change event ,you should store UserID to a variable like global variable or hiddenfields.
-Create a Button
in function=
function submitvalues()
{
//get stored userID here from variable
//perform submit here
}

Related

A controller with this name is not registered in Angulaj Js with Sql Database

I am currently learning Angular Js . I added the ADO.NET Entitly model in my project and Angular Js Packages as well. I am unable to do insert like user registration from my registration page. I lunch the developer tools and its showing following error ...
Module.js:5 Uncaught ReferenceError: angular is not defined
at Module.js:5
at Module.js:60
user.png Failed to load resource: the server responded with a status of 404 (Not Found)
load.png Failed to load resource: the server responded with a status of 404 (Not Found)
angular.min.js:42 Uncaught Error: [$injector:modulerr]
Here is my Code in Module.js file under MyScript Folder..
var app;
(function () {
var app = angular.module("myApp", []);
app.controller("Ctrl", ['$scope', function ($scope){
$scope.SaveUser = function () {
$("#divLoading").show();
var User = {
FName: $scope.fName,
LName: $scope.lName,
Email: $scope.uEmail,
Password: $scope.uPwd,
UserName: $scope.uName
};
var response = myService.AddUser(User);
response.then(function (data) {
if (data.data == "1") {
$("#divLoading").hide();
clearFields();
alert("User Created !");
window.location.href = "/Register/Login";
}
else if (data.data == "-1") {
$("#divLoading").hide();
alert("user alraedy present !");
}
else {
$("#divLoading").hide();
clearFields();
alert("Invalid data entered !");
}
});
}
function clearFields() {
$scope.fName = "";
$scope.lName = "";
$scope.Email = "";
$scope.Password = "";
$scope.UserName = "";
}
}]);
app.service("myService", function ($http) {
this.AddUser = function (User) {
var response = $http({
method: "post",
url: "/Register/AddUser",
data: JSON.stringify(User),
dataType: "json"
});
return response;
}
})
})();
Here is my code in controller.The name of my controller is RegisterController ..
public class RegisterController : Controller
{
public ActionResult Register()
{
return View();
}
//To check that user entered is already present or not.
public bool CheckUser(string user)
{
bool Exists = false;
using (HalifaxDatabaseEntities context = new HalifaxDatabaseEntities())
{
var uName = context.UserLogins.Where(x => x.UserName == user).ToList();
if (uName.Count != 0)
{
Exists = true;
}
}
return Exists;
}
//For saving the user details in database table.
public string AddUser(UserLogin usr)
{
if (usr != null)
{
if (CheckUser(usr.UserName) == false)
{
using (HalifaxDatabaseEntities context = new HalifaxDatabaseEntities())
{
UserLogin createUser = new UserLogin();
createUser.UserName = usr.UserName;
createUser.Firstname = usr.Firstname;
createUser.Lastname = usr.Lastname;
createUser.Email = usr.Email;
createUser.DateTimeCreated = DateTime.Now;
createUser.Password = Utility.Encryptpassword(usr.Password);
context.UserLogins.Add(createUser);
context.SaveChanges();
}
return "User created !";
}
else
{
return "User already present !";
}
}
else
{
return "Invalid Data !";
}
}
}
}
Here is HTML CODE ...
#{
Layout = null;
}
<html ng-app="myApp">
<head>
<title>Register</title>
<script src="~/Scripts/MyScript/Module.js"></script>
<script src="~/Scripts/angular.min.js"></script>
<link href="~/Content/bootstrap.css" rel="stylesheet" />
</head>
<body>
<div class="container" ng-controller="myCntrl">
<br />
<div class="row">
<img src="~/Content/Images/user.png" /><h4>Register User</h4>
<hr />
<br />
<div class="col-md-6">
<form name="userForm" novalidate>
<div class="form-horizontal">
<div class="form-group">
<div class="row">
<div class="col-md-3" style="margin-left: 15px; color: #5bc0de;">
First Name :
</div>
<div class="col-md-6">
<input type="text" class="form-control" placeholder="First Name" name="fName" ng-model="fName" required autofocus />
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-3" style="margin-left: 15px; color: #5bc0de;">
Last Name :
</div>
<div class="col-md-6">
<input type="text" class="form-control" placeholder="Last Name" name="lName" ng-model="lName" required autofocus />
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-3" style="margin-left: 15px; color: #5bc0de">
Email :
</div>
<div class="col-md-6">
<input type="email" class="form-control" placeholder="User's Email" name="uEmail" ng-model="uEmail" required autofocus />
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-3" style="margin-left: 15px; color: #5bc0de;">
Username :
</div>
<div class="col-md-6">
<input type="text" class="form-control" placeholder="Username" name="uName" ng-model="uName" required autofocus />
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-3" style="margin-left: 15px; color: #5bc0de;">
Password :
</div>
<div class="col-md-6">
<input type="password" class="form-control" placeholder="Password" name="uPwd" ng-model="uPwd" required autofocus />
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-3">
<input type="button" value="Save" ng-click="SaveUser();" class="btn btn-success" />
</div>
<div class="col-md-3">
#Html.ActionLink("Sign in", "Login", "Register", new { #class = "btn btn-info" })
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<div id="divLoading" style="margin: 0px; padding: 0px; position: fixed; right: 0px; top: 0px; width: 100%; height: 100%; background-color: #666666; z-index: 30001; opacity: .8; filter: alpha(opacity=70); display: none">
<p style="position: absolute; top: 30%; left: 45%; color: White;">
please wait...<img src="~/Content/images/load.png">
</p>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
Here is Screen Shot when I run the application Click here ]1
Any one help me to solved this Error
remove the first var app;
It is like you are declaring the app twice, try this
var app = angular.module("myApp", [])
.controller('myCntrl',['$scope',function($scope){
// your code here
}])
.service();
UPDATE
In the Module.js, you have defined the name of your controller app.controller("Ctrl",), but in the html File when you're calling it, you wrote ng-controller='myCntrl'
You have to give them the same name, that's it

how to get value of the editable text in angular controller

my index page is here
<div ng-app="CommentApp" ng-controller="MyController">
<div class=" col-md-12">
<div class="alert alert-info"><h2 class="text-center">Comment App</h2></div>
<div id="CommentList" class="container col-md-7" scroll="Comments" style="height:650px; overflow:scroll">
<div class="row" style="border:0px solid;padding:20px;" ng-repeat="Comment in Comments | orderBy:'LastUpdateTime'">
<div class="well well-sm row">
<div class="col-md-8">
**<h3><text style="color:mediumpurple;" e-form="rowform" data-ng-model="UpdateCommentText" editable-text="Comment.CommentText">{{Comment.CommentText || 'Empty'}}</text></h3>**
</div>
<div class="col-md-4 pull-right" style="margin-top:17px">
<div class="buttons pull-right">
<form editable-form name="rowform" ng-show="rowform.$visible" class="form-buttons form-inline">
<button type="submit" ng-disabled="rowform.$waiting" ng-click="EditComment()" class="btn btn-primary">
Save
</button>
<button type="button" ng-disabled="rowform.$waiting" ng-click="rowform.$cancel()" class="btn btn-default">
Cancel
</button>
</form>
</div>
<div class="buttons pull-right" ng-show="!rowform.$visible">
<button class="btn btn-primary" ng-click="rowform.$show()">Edit</button>
<button class="btn btn-danger" ng-click="RemoveComment(Comment)">Delete</button>
</div>
</div>
</div>
<div class="col-md-12 row" style="margin-bottom:10px" ng-repeat="img in Comment.Images">
<img style="margin-bottom:15px" src="{{img}}" />
</div>
<h2 class="pull-right" style="color:green;font-size:15px; margin-right:20px">By User {{Comment.Id}}</h2>
<h2 class="pull-right" style="color: darkviolet; font-size: 15px; margin-right: 20px">{{Comment.LastUpdateTime.slice(6,-2) | date: 'hh:mm a dd-MMM-yyyy' }}</h2>
<div class="clearfix"> </div>
<hr />
</div>
</div>
</div>
<div class="col-sm-10" style="font-size:17px">
<form novalidate name="f1" ng-submit="AddComment()">
<div style="color: red">{{Message}}</div>
<div class="col-sm-1">
<div class="glyphicon glyphicon-plus" style="height: 50px;border:1px solid; width: 50px; cursor:pointer;" onclick="getFile()">
<div style="height: 0px;width:0px; overflow:hidden;">
<input id="filesel" type="file" name="file" accept="image/*" onchange="angular.element(this).scope().selectFileforUpload(this.files)" required multiple />
</div>
</div>
<span class="error">{{FileInvalidMessage}}</span>
</div>
<div class="col-sm-6 pull-left">
<input type="text" placeholder="Enter Your Comment Here" style="height: 50px;font-size:30px;width:500px" name=" ufiledescription" ng-model="CommentText" class="{{(IsFormSubmitted?'ng-dirty' + (f1.uFileDescription.$invalid?' ng-invalid':''):'')}}" autofocus />
</div>
<div class="col-sm-3 pull-left">
<input class="btn btn-primary" style="height:50px;width:100px" value="Send" id="Submit" type="submit" />
</div>
</form>
</div>
</div>
my angular controller
app.controller("MyController", function ($scope, MyServices,$http) {
// Get All Comments
GetAllComments();
function GetAllComments() {
var getData = MyServices.getComments();
getData.then(function (cmnt) {
$scope.Comments = cmnt.data;
},
function () {
alert('Error in getting Comments');
});
};
// Add New Comment
$scope.AddComment = function () {
var Comment = {
CommentText: $scope.CommentText
};
var getData = MyServices.AddCmnt(Comment);
getData.then(function (ResultMsg) {
GetAllComments();
alert(ResultMsg.data);
});
ClearFields();
$scope.refresh();
};
// Edit The Comment
$scope.EditComment = function () {
Comment =
{
Id: Comment.Id,
CommentText: $scope.UpdateCommentText
}
alert(Comment.CommentText);
//var getData = MyServices.getCommentById(Comment.Id);
var getData = MyServices.EditCmnt(Comment);
getData.then(function (ResultMsg) {
alert(ResultMsg.data);
GetAllComments();
});
};
// Delete The Comment
$scope.RemoveComment = function (Comment) {
var getData = MyServices.DeleteCmnt(Comment);
getData.then(function (ResultMsg) {
alert(ResultMsg.data);
GetAllComments();
},
function () {
alert('Error in Deleting Comment');
});
}
//Clear Fields After Comment Addition
function ClearFields() {
$scope.CommentText = "";
angular.forEach(angular.element("input[type='file']"), function (inputElem) {
angular.element(inputElem).val(null);
});
};
});
in the index page the comment.commenttext which is editable text and coming from database on click of edit there will be a editable text box and after editing the text on click of save button i cant get value of edited text what shpold to in editcomment section to retrieve value of edited text?
i tried $scope.Comment.commenttext but it is undefined..
help me thanks in advance..
You have a double bind here:
<h3>
<text
style="color:mediumpurple;"
e-form="rowform"
data-ng-model="UpdateCommentText"
editable-text="Comment.CommentText"
>
{{Comment.CommentText || 'Empty'}}
</text>
</h3>
So basically you see what is binded with data-ng-model, not experssion in {{ }} Try getting UpdateCommentText value. Maybe this helps.

form data passing issue with MVC and Razor

I'm using razor html and attempting to post data to a function. I can get parts of the data to submit and go across just fine but other parts i can not.
#using (Html.BeginForm("Reply", "api/Reply", new { ID = Model.ID, UserName = Model.Username }))
{
<div id="mainArea" class="lightboxContent" style="display: block">
<div class="lightboxText">
<div class="responderTitleLeft">Select Profile: </div>
<div class="responderFormFloat">
<select name="profileSelector" class="select-style">
<option value="Select One" selected>Please Select Your Profile</option>
#foreach (var profile in Model.ProfileModels)
{
<option value="#profile.ProfileID">#profile.ScreenName</option>
}
</select>
</div>
<div class="responderActions">
<div id="Reply" class="TwtiterReply">
<a href="javascript:void(0)">
<img src="/images/engage/actions/reply.png" onclick="toggle('ReplyArea')" title="Reply to message" />
</a>
</div>
<div id="ReplyArea" style="display: none;" class="responderForm">
<div class="responderTitle">Reply</div>
<textarea id="MessageEdit" name="Message" onkeyup="return characterCount(this)" onchange="postChange(this.id, 'messagePreview');" rows="4" cols="50" style="resize: none">#Model.Username</textarea>
<p id="counter"><strong><span id="charCount">140</span></strong> more characters available.</p>
<div class="lightboxButtonsBar">
<input type="button" onclick="toggle('mainArea')" tabindex="3" value="Reply" />
<input type="button" class="cancel" tabindex="4" value="Cancel" />
</div>
</div>
</div>
</div>
</div>
<div id="confirmArea" class="confirmationArea" style="display: none">
<div class="warning">
<p><strong>Warning:</strong></p>
</div>
<div class="warningMessage">
<p>You are posting from #Model.ProfileModels with the message:</p>
<div class="messagePreviewArea" data-form="Reply">
<p>
<textarea id="messagePreview" readonly rows="4" cols="50" style="color: #ffffff; font-size: .9em; background-color: transparent; resize: none; border-color: #808080;"></textarea></p>
<input type="submit" tabindex="3" value="Confirm" />
<input type="button" onclick="toggle('mainArea')" tabindex="3" value="Cancel" />
</div>
</div>
</div>
}
public UserProfile Reply(string ID, string UserName, FormCollection form)
{
var pSelector = form["profileSelector"];
var message = form["Message"];
ApiService msgserv = new ApiService();
UserProfile up = UserProfile.GetFirst(new Guid(pSelector));
messenger.Reply(up.key, UserName, ID, message);
return up;
}
what i'm looking to get out of this form (in order of how it's show) ID, and username (they are provided by the model and i get those no problem.)
The ones i'm having issues with is the profile selector and the text area with the name message.
Can someone point me in the right direction on how to get a textarea and a select into a form?
The reason the select is not providing the model with data is because its name property is not set to corresponing property name in the model. The same goes for the text area. Generally speaking, if you want the form submit to fill those property you use the 'strongly-typed' helper methods, such as DropdownFor and CheckBoxFor. Or you can manually wire those up, try setting the name of the select element to "SelectedProfile" and changing the Reply action to: Reply(string ID,string Username,string SelectedProfile, FormCollection form)
To get from the textarea do something like this on your view #Html.TextArea("messagePreview"); But I would recommend saving things in your model if you can.

Add onsubmit event to call JS function in MVC3

I have a problem with calling JS method from form in MVC3 project: I have a "search"page without forms with two buttons - Search and Cancel. Click on search runs JS function runSearch in ProductDefinition.
<div id="productSearch-dialog" class="modal fade" style="width: 1000px; display: none">
<div class="modal-header">
<button class="close" aria-hidden="true" data-dismiss="modal" type="button">×</button>
<h3>Search Results</h3>
</div>
<div class="modal-body" style="height: 650px;">
<div>
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
</div>
<div id="searchresultcontain" class="grid">
</div>
<div id="Pagination" class="pagination">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" onclick="productDefinition.runSearch();">Search</button>
<button class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
How can I run this JS method (runSearch) when I press ? As far as I understand, this will be onsubmit event which is form event, so I am need to add form element with onsubmit property. I tried surrounding input field with BeginForm helper method:
#using (Html.BeginForm(new { onsubmit = "productDefinition.runSearch();" }))
{
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
<input type="submit" value="Submit" style="visibility: hidden" />
}
but it does not seem to be working - when I press enter I for some reason get source of the page and arrive at localhost/?onsubmit=productDefinition.runSearch() URL.
What can be the source of the problem and how can I get the same behaviour for onsubmit as for onclick?
#using (Html.BeginForm(new { onsubmit = "return runSearch();" }))
<script type="text/javascript">
function runSearch() {
// your logic to perform the search.
return true;
}
</script>
You need to use the following version of BeginForm method in order to specify html attributes.
However, it is considered a bad practice to use inline javascript so I would suggest to assign and id attribute to your form and handle its submit event in the external javascript file instead. If you are using jQuery for your project, here is a good example from their docs - http://api.jquery.com/submit/. In plan JavaSCript it is a bit more tricky but still easy to do.
#model Models.Person
<script type="text/javascript">
$(document).ready(function () {
$('#registerInputId').click(function () {
alert('what do you do before send? For example encrypt the password');
$('#Password').val(CryptoJS.MD5($('#Password').val()));
})
});
</script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal" style="display: inline-block; margin: 5% auto;">
<div style="font-size: 18px; margin-right:2px; margin-bottom:20px; text-align:right;">Add form</div>
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group" style="margin-top: 30px;">
<div class="col-md-offset-3 col-md-6">
<input id="registerInputId" type="submit" value="Register" class="btn btn-default" />
</div>
</div>
</div>
}
Form.Id is required if onsubmit handler implements generic functionality, applicable for multiple forms. (example : disabling all input fields)
Form
#using (Html.BeginForm(new {
id = "form24",
onsubmit = "return onSubmitHandler(id);"
}))
handler
<script type="text/javascript">
function onSubmitHandler(formId) { /*formId is form24 */ }
</script>

Model property, collection list is empty upon post to controller, potental issues with MVC with large size string list?

I am trying post a simple list within a model back to the controller. its rendered correctly but on post its always empty. I noticed when I use #Html.Hidden for the id and name are different for instance id becomes TestExceptionDisplay_[0]__Exception and name becomes TestExceptionDisplay[0].Exception. So I use an input type and try to make the way it likes to render but it does not work. I tried partial view, editor templates, nothing seems to work. TestException Display is a very simple list of an object called public List<RunLogEntryTestExceptionDisplay> TestExceptionDisplay { get; set; }
public class RunLogEntryTestExceptionDisplay
{
public string Exception { get; set; }
}
Snippet in the view which uses a for loop to render list, list is rendered fine but on post TestExceptionDisplay is NULL always:
#if (Model.TestExceptionDisplay != null)
{
for (var i = 0; i < Model.TestExceptionDisplay.Count; i++)
{
<tr>
<td>
#Model.TestExceptionDisplay[i].Exception
#*#Html.HiddenFor(m => m.TestExceptionDisplay[i].Exception)*#
<input name="RunLogEntry.TestExceptionDisplay_[#i]__Exception" type="hidden" value="#Model.TestExceptionDisplay[i].Exception" />
</td>
</tr>
}
}
OR this does not even work with editor templates upon post
#if (Model.TestExceptionDisplay != null)
{
#Html.EditorFor(x => x.TestExceptionDisplay)
}
Editor Template in Shared\EditorTemplates with the exact name of RunLogEntryTestExceptionDisplay
#model RunLog.Domain.Entities.RunLogEntryTestExceptionDisplay
<div>
#Html.EditorFor(x => x.Exception)
#Html.HiddenFor(x => x.Exception)
</div>
Rendered HTML looks like below, I did not copy the entire list, PLEASE NOT THAT THE ID AND NAME SEEM TO RENDER IN A DIFFERENT NAMING CONVENTION. IT HAPPENS in both cases, if I use an editor template or a for loop. thanks
<input id="TestExceptionDisplay_9__Exception" name="TestExceptionDisplay[9].Exception" type="hidden" value=""1404 TestException - Parameters:Unable to calculate result, assay is not calibrated for Assay Number (135), Assay Version (5), Track (1), Lane (2), and Reagent Lot Number (26600LI06)"" />
Complete View:
#model RunLog.Domain.Entities.RunLogEntry
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/errorCode.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/testexception.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/runLogEntry.js")" type="text/javascript"></script>
<script type="text/javascript">
var runlogListErrorsUrl = '#Url.Action("ListErrorCodes", "RunLogEntry")';
</script>
<fieldset>
<legend>Enter a new Run Log Entry</legend>
#using (Html.BeginForm("Create", "RunLogEntry", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<div class="exception">#(ViewBag.ErrorMessage)</div>
<div class="bodyContent">
<span class="leftContent">Load List File (Select): </span><span class="rightContent">
<input type="file" name="file" id="file1" style="width: 500px" />
</span>
</div>
if (Model.LoadListStoredFileName != null)
{
<div class="bodyContent">
<span class="leftContent">Attached Load List: </span><span class="rightContent">
#Html.ActionLink(Model.LoadListFileName, "Download", new { #file = Model.LoadListStoredFileName })
</span>
</div>
}
<div class="bodyContent">
<span class="leftContent">Output File (Select): </span><span class="rightContent">
<input type="file" name="file" id="file2" style="width: 500px" />
</span>
</div>
if (Model.OutputStoredFileName != null)
{
<div class="bodyContent">
<span class="leftContent">Attached Output: </span><span class="rightContent">
#Html.ActionLink(Model.OutputFileName, "Download", new { #file = Model.OutputStoredFileName })
</span>
</div>
}
<div class="bodyContent">
<span class="leftContent">Import Files: </span>
<button name="submit" class="art-button" type="submit" value="Upload" style="width: 100px">
Upload</button>
<button name="submit" class="art-button" type="submit" value="Remove" style="width: 100px">
Remove</button>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Operator")
</span><span class="rightContent">
#Html.DropDownList("OperatorID", String.Empty)
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Run ID")
</span><span class="rightContent">[Generated] </span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Run Start Date / Time")
</span><span class="rightContent">
#Html.EditorFor(model => model.RunDate)
#Html.DropDownList("Hour", ListHelpers.HourList())
:
#Html.DropDownList("Minute", ListHelpers.Minute15List())
#Html.DropDownList("AMPM", ListHelpers.AMPMList())
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("System")
</span><span class="rightContent">
#Html.DropDownList("SystemID", String.Empty)
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Run Type")
</span><span class="rightContent">
#Html.DropDownList("RunTypeID", String.Empty)
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Run Description")
</span><span class="rightContent">
#Html.TextAreaFor(model => model.RunDescription, new { style = "width: 600px; height=30px" })
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Assay Performance Issues")
</span><span class="rightContent">
#Html.DropDownList("AssayPerformanceIssues1", ListHelpers.YesNoList())
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Tests/Cycles Requested")
</span><span class="rightContent">
#Html.EditorFor(model => model.SPTestsRequested)
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Tests/Cycles Completed")
</span><span class="rightContent">
#Html.EditorFor(model => model.SPTestsCompleted)
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Run Status")
</span><span class="rightContent">
#Html.DropDownList("RunStatusID", String.Empty)
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Assay")
</span><span class="rightContent">
#Html.ListBoxFor(model => model.SelectedAssayIDs, new MultiSelectList(RunLog.Domain.Lists.GlobalList.AssayListItems(), "ID", "Name", Model.SelectedAssayIDs))
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Error Code")
</span><span class="rightContent"><span id="ChildDialogLink" class="treeViewLink">Click
here to Select Error Codes</span>
<br />
<span id="ErrorCodeDisplay" style="cursor: pointer; text-decoration: underline;">#(Model.ErrorDescription)</span>
#Html.HiddenFor(model => model.ErrorDescription)
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Test Exceptions")
</span><span class="rightContent"><span id="TestExceptionChildDialogLink" class="treeViewLink">
Click here to View Test Exceptions</span>
<br />
<span id="TestExceptionDisplayy"></span></span>
</div>
<div id="testExceptiontreeview" title="Dialog Title" style="font-size: 10px; font-weight: normal;
overflow: scroll; width: 800px; height: 450px;">
<div id="testExceptions">
</div>
<div id="inputTestExceptions">
<table class="grid" style="width: 450px; margin: 3px 3px 3px 3px;">
<thead>
<tr>
<th>
Exception String
</th>
<th>
Comment
</th>
</tr>
</thead>
#* #{var index = 0;}*#
#if (Model.TestExceptionDisplay != null)
{
for (var i = 0; i < Model.TestExceptionDisplay.Count; i++)
{
<tr>
<td>
#Model.TestExceptionDisplay[i].Exception
#Html.HiddenFor(m => m.TestExceptionDisplay[i].Exception)
</td>
</tr>
}
}
</table>
</div>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Service Entry Request")
</span><span class="rightContent">
#Html.DropDownList("ServiceRequest", ListHelpers.YesNoList())
</span>
</div>
<div class="bodyContent">
<span class="leftContent">
#Html.Label("Problem Description")
</span><span class="rightContent">
#Html.TextArea("ProblemDescription", new { style = "width: 600px; height: 30px" })
</span>
</div>
<p>
<input id="LogType" type="hidden" value="Run" />
<input id="ID" type="hidden" value="0" />
#if (Model.ExitCode == "1")
{
#Html.Hidden("ExitCode", Model.ExitCode)
}
else
{
<input id="ExitCode" type="hidden" value='0' />
}
</p>
#Html.HiddenFor(model => model.MaxReplicateId)
#Html.HiddenFor(model => model.MinReplicateId)
#Html.HiddenFor(model => model.OutputFileName)
#Html.HiddenFor(model => model.OutputStoredFileName)
#Html.HiddenFor(model => model.LoadListFileName)
#Html.HiddenFor(model => model.LoadListStoredFileName)
#Html.HiddenFor(model => model.MinTestCompletionDate)
#Html.HiddenFor(model => model.MaxTestCompletionDate)
<div class="bodyContent">
<span class="leftContent"></span><span class="rightContent">
<button name="submit" class="art-button" type="submit" value="Create">
Create</button></span>
</div>
}
</fieldset>
<script src="#Url.Content("~/Scripts/exitCode.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/exitCode.js")" type="text/javascript"></script>
<div id="treeview" title="Dialog Title" style="font-size: 10px; font-weight: normal;
overflow: scroll; width: 800px; height: 450px;">
<div id="errorCodes">
#Html.RenderTree(CacheHelper.ErrorCodes(), ec => ec.Name, ec => ec.Children.ToList(), ec => (ec.ID).ToString(), null, "e")
</div>
<div id="inputReps" style="display: none;">
</div>
</div>
Why are you expecting the list in the model you receive to be populated?
The model on POST is populated only with data from the form - MVC creates a new instance of your model class and populates the fields it can match up.
Because of this, the stock way of making sure your lists are populated is to have a helper method which populates them. You can then call this from either the original Get or the Post method to repopulate the lists.
The only time you'd expect to get a list populated in your model by PMV on postback is when the details to rebuild the list are available in form elements.
It's possible I've missed it in your reams of code but I can't see you doing that anywhere.
You should initialize your list in your first method, then pass to post method.

Categories