View is not sending right data to controller - asp.net-mvc

I have a very simple partial view and I am using ajaxform. In my partial view I have one sigle textArea and a Submit button.
The problem is whatever I write into the text area, It does not send the data to controller, rather it sends a text which is = "Comment".
If I dont write anything, the validation works perfect.
The Viewmodel:
public class NoteCommentViewModel
{
public Int32 Id { get; set; }
[Required(ErrorMessage="Hey, if you dont wanna write then why pressing the button !!")]
public string Comment { get; set; }
public DateTime CommentDate { get; set; }
public long UserId { get; set; }
public double Rating { get; set; }
public Guid NoteId { get; set; }
}
Controller:
//
//GET:/Notes/Comment/
public ActionResult Comment(string id)
{
ViewBag.NoteId = id;
var m = new NoteCommentViewModel()
{
NoteId = new Guid(id),
UserId = Convert.ToInt64(Session["LoginUserId"].ToString()),
//Comment=""
};
return PartialView(m);
}
//
//POST:/Notes/Comment
[HttpPost]
public ActionResult Comment(NoteCommentViewModel nvm)
{
NoteRatingComments comment = new NoteRatingComments();
comment.Comment = nvm.Comment; // Here I always have "Comment", regardless whatever I write in the page.
comment.EntryDate = DateTime.Now;
comment.NoteId = nvm.NoteId;
comment.UserId = nvm.UserId;
comment.Rating = 3.00;
dc.NoteRatingComments.AddObject(comment);
dc.SaveChanges();
return Content(Boolean.TrueString);
}
The view:
<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>
#using (Ajax.BeginForm("Comment", "Notes", null, new AjaxOptions
{
UpdateTargetId = "Comment-message",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "commentSuccess"
}, new { id = "commentForm" }))
{
<div style="margin-top:20px;">
<div id="commentSuccess"></div>
<div class="comentPic">
#{
long UserId = Convert.ToInt64(Session["LoginUserId"].ToString());
string Fullname = Session["LoginUserFullName"].ToString();
}
<img src='https://graph.facebook.com/#UserId/picture' height="100px" width="100px"/>
</div>
<div class="commentText">
#Html.HiddenFor(m => m.UserId)
#Html.HiddenFor(m=>m.NoteId)
#Html.TextAreaFor(m => m.Comment, new { style = "width:600px;height:120px;" })
<br />
#Html.ValidationMessageFor(m => m.Comment)
<div style="text-align:right;">
<input type="submit" value="Comment" name="comment" class="btn"/>
</div>
</div>
<div class="clear"></div>
</div>
}
Here is the screen shot of the error...for better understanding. I am writing "data" in the view but in the controller I am getting "Comment"..Where is it coming from??
WOuld be great if someone can help me to identify the problem...!!

The problem is that your submit button's name attribute is the same as the Comment textarea name attribute.
To resolve this you need to change the submit button's name to something else than "comment" or remove the name attribute from your submit button, so change:
<input type="submit" value="Comment" name="comment" class="btn"/>
To
<input type="submit" value="Comment" class="btn"/>
Because the Ajax.BeginForm uses the the jQuery .serializeArray() method which - because your submit button has a name and this input triggers the submit - also sends the submit button's value "Comment" to the server.

I am not sure what exactly your problem is. But the below code should work.
public class NoteCommentViewModel
{
public Int32 Id { get; set; }
[Required(ErrorMessage=" Your Error message")]
[DataType(DataType.MultilineText)]
public string Comment { get; set; }
//other properties
}
And in your View, Use it like this
#Html.EditorFor(m => m.Comment)

actually your code is very confusing. in your view u didnt use Model and seems you use m as your model and as i know this is completely wrong.i dont know your view is rendering but wherever you use m=>m.sth the second m must be nothin.instead you must define your #model NoteCommentViewModel at first of cshtml file and then use Model instead of second m

Related

MVC Return Fields to Controller

I've got a controller to retrieve and return values for my drop down, and a second, that when an option from the dropdown is selected, uses the values (Title and ID) in an API Request.
Controllers
public ActionResult GetEpics()
{
//Code to retrieve list
Epics = new GetEpicsViewModel();
Epics.Epics = epicsList;
return View(Epics);
}
[HttpPost]
public ActionResult Build(GetEpicsViewModel epic)
{
GetEpicsViewModel epicTest = epic;
//API Request
return View();
}
This is displayed in my drop down list as below:
View
#using (Html.BeginForm("Build", "GetEpics", FormMethod.Post))
{
<label for="input_OutputType"> Process: #Html.DropDownListFor(model => model.Id, new SelectList(Model.Epics, "Id", "Title")) </label>
<input type="submit" value="Submit" />
}
This works fine, but how would I then go about passing both the Title and ID to my controller?
I can pass the ID through fine, but cant figure out how to pass the Title as well.
Screenshot
Models
public class DevOpsEpic
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
and
public class GetEpicsViewModel
{
public string Id { get; set; }
public string Title { get; set; }
public List<DevOpsEpic> Epics { get; set; }
}
Realise this is probably a really simple answer, but just cant figure it out!
You can use jQuery for that, so when your dropdown is changed, set title value in hidden file.
#using (Html.BeginForm("Build", "GetEpics", FormMethod.Post))
{
<label for="input_OutputType"> Process: #Html.DropDownListFor(model => model.Id, new SelectList(Model.Epics, "Id", "Title"),new { name = "Id" }) </label>
<input type="hidden" id="Title" name="Title" />
<input type="submit" value="Submit" />
}
$('#dropdownId').change(function(){
$('#Title').val($('#dropdownId option:selected').text());
});

ASP.NET MVC - Having trouble obtaining pull-down selection in control

I am having trouble accessing a user's pull-down selection from within the controller once the user has selected a value and submitted it via the view.
The pull-down menu is populating correctly and I've written a simple JavaScript function that alerts the user when a selection change is made. Via the alert, I see the RoleID value. I just can't seem to access it in the controller. Please see my code below and help! Thank you in advance.
Model:
public class dbModels
public class UserAccessRequestViewModel
{
dbEntities _dbEntities = new dbEntities();
public IEnumerable<ActiveRoles> Roles { get; set}
public Guid selectedRoleID { get; set:}
public class ActiveRoles
{
public Guid RoleID { get; set; }
public string RoleName { get; set; }
}
public List<ActiveRoles> GetActiveRoles()
{
var ActiveRoles = dbEntities.LU_ROLE.Where(x => x.ACTIVE)
.Select (x => new ActiveRoles { RoleID = x.ROLE_ID, RoleName = x.ROLE_NAME }).ToArray();
return activeRoles.ToList();
}
}
View:
<div class="text-left" style="margin:4px; padding:4px">
<h2>Assign Role</h2>
#Html.DropDownList(model => model.selectedRoleID, new SelectList(Model.Roles, "RoleID", "RoleName"), new { #onchange = getUserRoleID(this)" })
</div>
<div class="form-actions no-color" style="margin:4px; padding:4px">
#using (Html.BeginForm("Approve", "UserAccessRequestManagement", FormMethod.Post))
{
<input type="submit" value="Approve" class="btn btn-default" />
}
#Html.ActionLink("Back to List", "Index")
</div>
Control:
public class UserAccessRequestManagementController : Controller
dbModels.UserAccessRequestViewModel _UserAccessRequestViewModel = new dbModels.UserAccessRequestViewModel();
[HttpPost, ActionName("Approve")]
public ActionResult Approve(Guid id)
{
Guid RoleID = _UserAccessRequestViewModel.selectedRoleID;
}
Your select input should be part of your form.
<div class="form-actions no-color" style="margin:4px; padding:4px">
#using (Html.BeginForm("Approve", "UserAccessRequestManagement", FormMethod.Post))
{
<div class="text-left" style="margin:4px; padding:4px">
<h2>Assign Role</h2>
#Html.DropDownList(model => model.selectedRoleID, new SelectList(Model.Roles, "RoleID", "RoleName"), new { #onchange = getUserRoleID(this)" })
</div>
<input type="submit" value="Approve" class="btn btn-default" />
}
#Html.ActionLink("Back to List", "Index")
</div>
Also you have to make sure what you want to get in your Controller action as a parameter.
If you just need a guid then change the parameter name to selectedRoleID as the name of the input element should match with your action parameter. In case you want to take entire model as parameter then you have to mention it correctly in action defintion.
In case you want to get entire model in your POST action
public class UserAccessRequestManagementController : Controller
dbModels.UserAccessRequestViewModel _UserAccessRequestViewModel = new dbModels.UserAccessRequestViewModel();
[HttpPost, ActionName("Approve")]
public ActionResult Approve(UserAccessRequestViewModel model)
{
Guid RoleID = model.selectedRoleID;
}
OR make it like this In case you just want a selected guid in your POST action
[HttpPost, ActionName("Approve")]
public ActionResult Approve(Guid selectedRoleID)
{
Guid RoleID = selectedRoleID
}

How to input multiple types with one controller action MVC5

I'm really new to MVC and I am trying to be clever..
I have one View that displays one question but offers various methods of responding;
#using Microsoft.AspNet.Identity
#model Template.Models.Question
#{
ViewBag.Title = "View question";
var qtype = Model.QuestionTypeId;
ViewBag.Number = Model.Id - 7;
Html.BeginForm("ViewQuestion", "Question", FormMethod.Post, new { #class = "form-horizontal", role = "form" });
}
<div>
<h4>Question ##ViewBag.Number</h4>
<hr />
<h1> #Model.Question1</h1>
</div>
#Html.AntiForgeryToken()
<div class="form-group">
#switch (qtype)
{
case 1:
// Textbox
#Html.TextArea("Answer", new { #class = "form-control", rows = "4", col = "5" });
break;
case 2:
// Dropdown
<select class="form-control" id="Answer">
#foreach (var item in Model.QuestionOptions.OrderBy(o => o.QuestionOptionRanking))
{
<option value="#item.QuestionOption1">#item.QuestionOption1</option>
}
</select>
break;
case 3:
// Checkbox
<div class="checkbox">
#foreach (var item in Model.QuestionOptions.OrderBy(o=> o.QuestionOptionRanking))
{
<input type="checkbox" name="Answer" value="#item.QuestionOption1" /> #item.QuestionOption1 <br />
}
</div>
break;
case 4:
// Radio buttons
foreach (var item in Model.QuestionOptions.OrderBy(o => o.QuestionOptionRanking))
{
<div class="radio">
<label>
<input type="radio" name="Answer" value="#item.QuestionOption1" />
#item.QuestionOption1
</label>
</div>
}
break;
}
</div>
<input type="hidden" name="QuestionId" value="#Model.Id" />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Answer" />
</div>
</div>
My ViewModel;
public class ResponseViewModel
{
[Required]
public string UserId { get; set; }
[Required]
public int QuestionId { get; set; }
[Required(ErrorMessage = "Please answer the question before submitting")]
public string Answer { get; set; }
[Required]
public string Source { get; set; }
[Required]
public string Status { get; set; }
[Required]
public System.DateTime DateStamp { get; set; }
public Nullable<int> Duplicate { get; set; }
public virtual Question Questions { get; set; }
public object SelectedValue { get; set; }
public virtual ICollection<QuestionOption> QuestionOptions { get; set; }
}
And finally my action;
[HttpPost]
public ActionResult ViewQuestion([Bind(Include = "QuestionId, Answer")] ResponseViewModel responseViewModel)
{
//var optionSelected = responseViewModel.Answer;
//if (optionSelected == null)
//{
// optionSelected = responseViewModel.Answer.SelectedValue();
//}
Response re = new Models.Response();
re.Answer = responseViewModel.Answer;
if (re.Answer == null)
{
re.Answer = "Work in progress!";
// re.Answer = responseViewModel.SelectedValue();
// re.Answer = int.Parse(SelectList["Question.QuestionOption1"]);
}
re.UserId = User.Identity.GetUserId();
re.QuestionId = responseViewModel.QuestionId;
re.Source = "Web";
re.Status = "New";
re.DateStamp = System.DateTime.Now;
db.Responses.Add(re);
db.SaveChanges();
return RedirectToAction("ViewQuestion");
}
If you examine the view you will notice an "Answer" can be a textbox, checkbox, radio buttons or dropdown. Everything works fine on display, some questions have dropdownlists, others radio button, etc. Its the posting that's got me stumped. If you notice I have not used HTML Helpers, but old fashion HTML as I kept getting errors that the types I've mentioned did not exist in my helpers.
Post works fine if its a text box, but if you look at my controller action you will see a few commented out attempts to also catch the values if it is one of the other controllers..
I thought I was being clever with my cases, but now I can't seem to write any code that will capture the selected, or checked options.
Any advice would be great!
I can think of one possibility off the top of my head. In MVC, you can have more than one form on a page. Instead of wrapping all of your cases in one form, make each case it's own form with it's own submit button, and have an action method for each one.
EDIT
Also in looking at your code, you're going to have a problem with the checkboxes because your Answer property is a String and if more than one checkbox is checked you're going to get an array

Retrieving values from partial view during post method

I have a view which contains a dropdown list and on dropdownlist item being selected I load a partial view. And when the form is submitted I want to be able to get both the values from main view and partial view during form submit.
Here is the main view
#model AdminPortal.Areas.Hardware.Models.CreateModule
#{
ViewBag.Title = "Create Module";
Layout = "~/Views/shared/_BootstrapLayout.basic.cshtml";
}
#Html.ValidationSummary(true)
<fieldset class="form-horizontal">
<legend>Add a Module <small>Create</small></legend>
#using (Html.BeginForm("CreateModule", "Module", new{id="AddModuleForm"}))
{
#Html.ValidationSummary(true)
<div class ="controls">
<div class="input-block-level">#Html.TextBoxFor(model => model.ModuleId, new {#placeholder = "ModuleID"})</div>
<br/>
<div class ="input-block-level" id="selectedModuleTypeName">#Html.DropDownListFor(model => model.SelectedModuleTypeName, Model.TypeNames,"Select Moduletype", new{id = "ModuleList"})</div>
<br/>
<div id="partialDiv"></div>
</div>
<div class="form-actions" id="buttons">
<button type="submit" class="btn btn-primary" id="Submit">Save changes</button>
#Html.ActionLink("Cancel", "ModuleList", null, new { #class = "btn " })
</div>
}
</fieldset>
<div>
#Html.ActionLink("Back to List", "ModuleList")
</div>
<script>
$("#buttons").hide();
$("#ModuleList").on("change", function() {
var modId = $(this).val();
$.get('#Url.Action("GetModulePropertyName", "Module")', { moduleTypeValue: modId }, function(result) {
$("#partialDiv").html(result);
});
//uncomment following section to check if the partial view is working properly
/*.done(function() { alert("done"); })
.fail(function() { alert("fail"); })
.always(function() { alert("completed"); });*/
});
$("#buttons").show();
</script>
and here is the partial view
#model IEnumerable<string>
#foreach(var names in Model)
{
<div class="input-block-level">#Html.TextBoxFor(m=>names, new{Value="", placeholder=names})</div>
<br/>
}
Here is my model
public class CreateModule
{
//Empty form to handle form serialization
public CreateModule()
{
}
[Required]
public string ModuleId { get; set; }
[DataType(DataType.DateTime)]
public DateTime DateEntered { get; set; }
[Required]
public string SelectedModuleTypeName { get; set; }
public IEnumerable<SelectListItem> TypeNames { get; set; }
public List<Property> Properties { get; set; }
}
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
Here is the method that script in main view forwards to
[HttpGet]
public ActionResult GetModulePropertyName(string moduleTypeValue)
{
var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
var modulePropertyNames = _repository.GetModuleKindPropertyNames(moduleTypeValue);
return PartialView("GetModulePropertyName",modulePropertyNames);
}
and finally here is httppost method for the main view
[HttpPost]
public ActionResult CreateModule(CreateModule moduleV)
{
var module = new Module
{
ModuleTypeId = Convert.ToInt64(moduleV.SelectedModuleTypeName),
ModuleId = moduleV.ModuleId,
DateEntered = moduleV.DateEntered,
};
if (ModelState.IsValid)
{
_repository.AddModule(module);
Success("Module added successfully!");
return RedirectToAction("ModuleList", "Module", new {area = "Hardware"});
}
Error("Something went wrong!");
return RedirectToAction("CreateModule", "Module", new { area = "Hardware" });
}
Current situation:
When the form is posted, the properties value of the model that is being passed via partial view is null. I get other values, like typename, Module ID.
What I'd want:
I also want to get the value of properties that is being passed via partial view.
You don't have any input field for the Properties property anywhere in your form. So it will always be null. That's normal.
Here's how you could proceed. Start by setting the correct navigational property so that the helper generates correct names of the corresponding input fields.
Also make sure that you are passing an IEnumerable<Property> model to the partial if you want to be able to get them back correctly:
[HttpGet]
public ActionResult GetModulePropertyName(string moduleTypeValue)
{
var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
IList<Property> model = ...
return PartialView("GetModulePropertyName", model.ToList());
}
and in your partial view use an editor template:
#model IList<Property>
#{
// This indicates the current navigational context to the helpers
ViewData.TemplateInfo.HtmlFieldPrefix = "Properties";
}
#Html.EditorForModel()
and the last step is to define a custom editor template for the Property class: ~/Views/Shared/EditorTemplates/Property.cshtml (note that the name and location of the template is important)
#model Property
<div class="input-block-level">
#Html.HiddenFor(m => m.Name)
#Html.TextBoxFor(m => m.Value, new { placeholder = Model.Name })
</div>
<br />
Try using the
List<Property>
as a model in your partial view and pass the CreateModule.Properties as model from your View
The problem is model binder can not figure out there
#Html.TextBoxFor(m=>names, new{Value="", placeholder=names})
belongs to as the "names" is not a property on your model class. If you need to bind to the CreateModule.Properties you need to change the partial view to emit textboxes with aproprate names, like this one:
#model IEnumerable<string>
#
{
int i=0;
}
#foreach(var names in Model)
{
<div class="input-block-level">#Html.TextBox("Properties[" + i + "].Value")</div>
<br/>
}

Model returning null value

This is my code for my model
public class ManufacturerModel
{
public int ProductTYpeId { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public List<SelectListItem> manf { get; set; }
public Manufacturer manufacturer { get; set; }
}
This is my code in cshtml file
#using (Html.BeginForm("addmanufacturer", "Admin", FormMethod.Post, new { id = "formPageID" }))
{
<div class="row">
<label>Select Existing Manufacturer<span style="color: Red">*</span>:</label>
<div class="formRight">
#Html.DropDownList("Id", Model.manf)
</div>
</div>
<div class="row">
<label>Manufacturer Name<span style="color: Red">*</span>:</label>
<div class="formRight">
#Html.TextBoxFor(m => m.manufacturer.name)
#Html.ValidationMessageFor(m => m.manufacturer.name)
</div>
</div>
}
I am posting this form and when I am trying to fetch the value from the manfacurer ie - ManufacturerModel manufacturer = new ManufacturerModel();
using a model object all the value are coming out null.
in the text box If I replace it with m => m.Name then I am able to get proper value of Name.
can any one suggest what the problem is
I am using the manf to bind a dropdown. If In case I post back the form and the if it is return the value becomes blank, I need to refill the value..
public ActionResult addmanufacturer(string id)
{
if (id == null)
id = "0";
ManufacturerModel manufacturer = new ManufacturerModel();
manufacturer.ProductTYpeId = Convert.ToInt32(id);
manufacturer.manf = GetManf();
manufacturer.Id = -1;
return View(manufacturer);
}
I think problem will be becouse of:
#using (Html.BeginForm("Action", "Controller", FormMethod, HTML ATTRIBUTES )) { }
You probably want this overload:
#using (Html.BeginForm("Action", "Controller", Route Values, FormMethod, html attributes )) { }
Important is say him that you want route values and not a html atrributes, so try this
#using (Html.BeginForm("addmanufacturer", "Admin", new { id = "formPageID" }, FormMethod.Post, null )) { }
Hope, it helps.
M.

Resources