Form does not perform GET on submit - html

My model contains:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
My controller contains:
public ActionResult Index(int? personId)
{
var people = db.People; // all people in my database
ViewBag.People = new SelectList(people, "Id", "Name", personId);
return View();
}
My view contains:
#using (Html.BeginForm(null, null, FormMethod.Get, new { #class = "form-inline" }))
{
#Html.DropDownList("personId", ViewBag.People as SelectList, "All people", new { #class = "form-control select-submit" })
}
And I have this piece of Javascript:
<script type="text/javascript">
(function ($) {
$(".select-submit").change(function () {
$(this).parents("form").submit();
alert("form submitted!");
});
})(jQuery);
</script>
When I select a person from the DropDownList, I see the alert popup, and the page refreshes. When I select the default option ("All People"), I also see the popup, but the page does not refresh.
I want "personId" to be set to "" on selecting the default option. How can I achieve this?

Ah, I found it. After inspecting the html, I noticed the form was using data validation. These html attributes were getting added after selecting a person:
data-val="true" data-val-number="The field Int32 must be a number." data-val-required="The Int32 field is required."
The form couldn't be submitted because "" is not valid for an Int32. Adding this html attribute to the DropDownList solved it:
data_val = false

Related

Cascading Drop Down List in MVC w/ SQL Database

I have two drop down lists which are District & School. I would like whenever I choose a district from the list, the values that are in the school list will change at the same time. I am using ajax to try and post the data to another controller but the school list does not change at all. It contains the names of all schools no matter which district I select. I am thinking it has something to do with the line Schools = new SelectList(db.Schools.ToList(), "schoolID", "name")in my SchoolDistrictInformation controller. Here is what I am working with so far:
The security code is a code that must be entered and corresponds with the selected district. It must match with the code in the database or the form will not be submitted.
View Model:
public class DistrictSchoolListViewModel
{
public SelectList Districts { get; set; }
public SelectList Schools { get; set; }
public string SelectedSchool { get; set; }
public string SelectedDistrict { get; set; }
[Required(ErrorMessage = "This code is required")]
public string DistrictCode { get; set; }
}
Controllers:
public ActionResult SchoolDistrictInformation()
{
var viewModel = new DistrictSchoolListViewModel()
{
Districts = new SelectList(db.Districts.ToList(), "leaID", "name"),
Schools = new SelectList(db.Schools.ToList(), "schoolID", "name")
};
return View(viewModel);
}
[HttpPost]
public ActionResult GetSchools(DistrictSchoolListViewModel model)
{
var selectedDistrict = model.SelectedDistrict;
var schools = findSchools(selectedDistrict);
IEnumerable<SelectListItem> filteredSchools =
schools.Select(m => new SelectListItem { Text = m.name, Value = m.schoolID.ToString() });
return PartialView("SchoolDistrictInformation", filteredSchools);
}
School Table Query:
internal IQueryable<School> findSchools(string district)
{
var query = from School in db.Schools
where School.leaID.Equals(district)
select School;
return query;
}
School District Information View:
#model Staff_Form.Models.DistrictSchoolListViewModel
<h2>Select District and School from list</h2>
<script type="text/javascript" src="/scripts/jquery-1.4.4.js"></script>
<script type="text/javascript">
$('#SelectedDistrict').on('change', function () {
$.ajax({
type: "POST",
url: 'Controller/GetSchools',
data: $(this).val(),
success: function (response) {
$('#SelectedSchool').html(response);
}
});
});
</script>
<div>
<form action="#Url.Action("StaffInformation", "Staff")" method="get">
District: #Html.DropDownListFor(m => m.SelectedDistrict, Model.Districts, "----Select----")
Security Code: #Html.TextBoxFor(m => m.DistrictCode) <br />
School: #Html.DropDownListFor(m => m.SelectedSchool, Model.Schools, "----Select----")
<input type="submit" value="Submit" />
</form>
</div>
Get Schools View:
#model System.Collections.Generic.IEnumerable<System.Web.Mvc.SelectListItem>
#{ Layout = null;}
#foreach (var school in Model)
{
<option value="#school.Value">#school.Text</option>
}
I appreciate any and all help given towards the solution of this question. Thank you!
Your script is before the the element with id="SelectedDistrict" and not wrapped in $(document).ready() so your attaching an event to an element which does not even exist at that point.
Move the script to the bottom of the page (immediately before the closing </body? tag and/or wrap it inside document.ready
$(document).ready(function() { // or $(function() {
$('#SelectedDistrict').on('change', function () {
....
});
});
Side note: Update your version of jquery to a recent version and consider returning json to populate your 2nd dropdown (refer this answer)
You should include the property name when you pass the district back to the GetSchools action
$('#SelectedDistrict').on('change', function () {
$.ajax({
type: "POST",
url: 'Controller/GetSchools',
data: { SelectedDistrict: $(this).val() },
success: function (response) {
$('#SelectedSchool').html(response);
}
});
});

Pass string to action method overload

So what I want to do is take a string from a textarea and pass it to an action method overload (string paramJSON).
Action method:
public ActionResult SendMail(string templateName, string receiver, string paramJSON)
{
var paramDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(paramJSON);
new SendMailClient().Send(templateName, receiver, paramDictionary);
if(Request.IsAjaxRequest())
{
return RedirectToAction("SendPartial", "TestMail");
}
return View();
}
Textarea:
#Html.TextAreaFor(a => a.TestParametrar, new { id = "paramTxt" })
Your html helper
#Html.TextAreaFor(a => a.TestParametrar, new { id = "paramTxt" })
generates a textarea with name="TestParametrar". When you submit a form, it sends back the values of each controls name and value attributes in this case TestParametrar: 'The text you entered' You method needs to include a parameter with the same name, for example
public ActionResult SendMail(string TestParametrar, ....)
and the value of the parameter will be the text entered in the form control.
However, since you view is based on a model, then it is better to just post back to the model and all properties will be bound
public ActionResult SendMail(YourModel model)
which has the added benefit of validating your properties. For example, if property TestParametrar has the [Required] attribute, then if the user does not enter a value, ModelSTate will be invalid and the view can be returned for correction.
#using (Html.BeginForm("SendMail2"))
{
#Html.TextAreaFor(a => a.TestParametrar, new { id = "paramTxt" })
<input type="submit" value="Send Message" />
}
And:
public ActionResult SendMail2(string TestParametrar)
{
return SendMail("myTemplate", "hello#world.com", TestParametrar);
}

Input type = "file" loses file automatically?

I have two inputs of type file, one in a partial view, and another in main page
In partial view
<input type="file" name="image" id="image" onchange="readURL(this)"/>
In main page
<input type="file" name="userProfilePic" id="userProfilePic" style="display:none" />
What I want is that when a user changes image/file on the visible file upload, the image/file should be updated on main/other input too. Here's my code.
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imagePreview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
// window['profilePic'] = input.files[0];
$('#userProfilePic').get(0).files[0] = input.files[0];
return false;
}
The Error
The error is quite weird, when I open my console, and check for files, it shows up sometime, and a moment later it don't.
In my console window
$('#userProfilePic').get(0).files[0]
File (file object details)
....
(after a second)
$('#userProfilePic').get(0).files[0]
undefined
And it isn't happening the first time only. Say sometimes, it shows the values for 5-6 times, then 7th time it won't...
$('#userProfilePic').get(0).files[0]
File (file object details)
....
(after a second)
$('#userProfilePic').get(0).files[0]
File (file object details)
....
(after a second)
$('#userProfilePic').get(0).files[0]
File (file object details)
....
(after a second)
$('#userProfilePic').get(0).files[0]
undefined
That's all the code I have, there is no other code. Now, as you can see in the code, I also set window[profilePic] to the file object. But if I check that in console window, it always shows no matter what? How is this happening?
The problem
I need to submit the form, but when I do, the image (the input file) is being sent as null, but sometimes as a valid file. As I explained earlier, when I check the value in console, it shows for first time, or some random number of times, then all of a sudden it is gone, while the variable that I set on window (window[profilePic]) always have that file object.
In case someone is wondering, the original/visible file input where user actually selects the file always has the value.
You cant do this for security reasons , all files uploaded via input type="file" have to be done manually by the user.
However as long as the user will upload an image anyway , you should do all the process you want in your server side script.
for further info , please refer to this post here :
How to set a value to a file input in HTML?
Why you try to use two inputfile for the same file?
if you try to make a form in a PartialView with a inputfile and extra data? I answered a very similar question here:
File upload in MVC when used in bootstrap modal returns null
1) make a model for used in the form with all elements for the form,
2) declare the model in the first line in the partial view
3) pass as parameter the model to the post function.
4) you use a Partial view, well is possible use this view in differents pages, you need specify the control to treatement the form.
An Example in code:
Model:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class PartialFormModel
{
[Required]
[StringLength(200)]
public string FileName { get; set; }
[StringLength(200)]
public string Title { get; set; }
[StringLength(1000)]
public string Description { get; set; }
public int? Order { get; set; }
[NotMapped]
public HttpPostedFileBase ImageFile { get; set; }
}
PartialVIEW:
#model YOURSPACENAME.Models.PartialFormModel
#using (Html.BeginForm("YourActionName", "YourControllerName", FormMethod.Post, new { #class = "form-horizontal", #role = "form", #enctype="multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(model => model.FileName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FileName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FileName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ImageFile, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.ImageFile, new { #class = "form-control", type = "file" })
</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>
}
CONTROLLER
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult YourActionName(PartialFormModel obj)
{
if (ModelState.IsValid)
{
//your options
}
return PartialView("_EditSlider");
}
Considering that:
For security reasons you can't set value of input type="file"
programmatically.
Changing the type of an <input> throws a security error in some
browsers (old IE and Firefox versions).
I don't know actually what you want. But I exhort you to create a new input element, set its type to the one you want, say file, and set its properties according to your need. like this:
<script>
function createInputType(_type, _value, _name, _id, _class) {
var newObject = document.createElement('input');
newObject.type = _type;
newObject.value = _value;
newObject.name = _name;
newObject.id = _id;
newObject.className = _class;
return newObject;
}
</script>

Unable to set property on ViewModel when selected option from dropdown List ---MVC4

Unable to find where I'm doing wrong. Help would be appreciated.Thanks!
In my viewmodel I have property ListValues which contain data for dropdownlist. I'm trying to set property(SelectedItem) on viewmodel when a selection is made in dropdownlist. But it is not updating the value when something is selected in dropdownlist. In this example I'm using javascript function to test if the value has been set, but it always says variable undefined.
My ViewModel:
public class ViewModel
{
private readonly List<SelectListItem> items;
public ViewModel()
{
items = new List<SelectListItem>();
items.Add(new SelectListItem() { Text = "Texas", Value = "1", Selected = true });
items.Add(new SelectListItem() { Text = "Illinios", Value = "2", Selected = false });
items.Add(new SelectListItem() { Text = "New York", Value = "3", Selected = false });
items.Add(new SelectListItem() { Text = "Kansas", Value = "4", Selected = false });
ListValues = items;
}
public string SelectedItem { get; set; }
public IEnumerable<SelectListItem> ListValues { get; set; }
}
Action Method:
public class EmployersController : Controller
{
//
// GET: /Employers/
public ActionResult Index()
{
ViewModel vm = new ViewModel();
return View(vm);
}
}
View:
#using System.Collections
#model DemoMVCApplication.Models.ViewModel
<script src="~/Scripts/Custom/default.js"></script>
#{
ViewBag.Title = "Index";
}
#Html.DropDownListFor(model => model.SelectedItem, Model.ListValues)
<button id="button123" onclick="process(#Model.SelectedItem);">Call Script</button>
<h2>Index</h2>
javascript to test if value has been set
function process(x) {
var result = x;
}
The x always says undefined
this is a duplicate of: How to write a simple Html.DropDownListFor()?
however: <%= Html.DropDownListFor(n => n.MyColorId, new SelectList(Colors, "ColorId", "Name")) %>
is the code from that answer that you require, this being that you also need to convert your type to selectList, despite this already being that type in the Model.

How to pass value of Html.Dropdownlist to Controller

I am dynamically generating a dropdownbox.
I am trying to send the selected value in dropdown box as one of the fields of a model to controller.
#using (Html.BeginForm("AddItem", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<label>
Category:</label>
#Html.DropDownList("Category", (IEnumerable<SelectListItem>)ViewData["CategoryList"])<br />
<label>
Sku:</label>
#Html.TextBox("newItem.Sku")<br />
<label>
Title:</label>
#Html.TextBox("newItem.Title")<br />
I am able to send all the values as a part of model, except the value of Category(dropdownbox value), hence making the function in controller to fail..
ANSWER: Renaming the Dropdownlist "Category" to = "newItem.Category", did the work, basically it should match the model name.
Create a ViewModel for your Item with Properties to hold all Categories and SelectedCategoryId value
public class ItemViewModel
{
public int ItemId { set;get;}
public string SKU { set;get;}
public string SelectedCategoryId { get; set; }
public IEnumerable<SelectListItem> Categories{ get; set; }
}
In your home controller, Create Action method for Add where you create an object of ItemViewModel, Set the Categories and return to the View which is strongly typed.
public ActionResult AddItem()
{
ItemViewModel objNewItem=new ItemViewModel();
objNewItem.Items = new[]
{
new SelectListItem { Value = "1", Text = "Perfume" },
new SelectListItem { Value = "3", Text = "Shoe" },
new SelectListItem { Value = "3", Text = "Shirt" }
};
return View(objNewItem);
}
The Strongly typed View
#model ItemViewModel
#using (Html.BeginForm("AddItem", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
Category:
#Html.DropDownListFor(x => x.SelectedCategoryId ,new SelectList(Model.Categories,"Value",Text"), "Select..")
<input type="submit" value="Add" />
}
And have the HTTPPOST AddItem method in your Home Controller
[HttpPost]
public ActionResult AddItem(ItemViewModel objItem)
{
//Now you can access objItem.SelectedCategoryId and do what you like to do...
}
Your DropDown is bound to a field called Category. So you must have such field on your view model.
public class MyViewModel
{
public string Category { get; set; }
...
}
and your action:
[HttpPost]
public ActionResult AddItem(MyViewModel model)
{
// model.Category will contain the selected value
...
}
Also note that this property must be a simple scalar value (string, int, ...) and not a complex object.
And once you have an adapted view model you could use the strongly typed versions of the helpers:
#model MyViewModel
#using (Html.BeginForm("AddItem", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.LabelFor(x => x.Category)
#Html.DropDownListFor(x => x.Category, Model.Categories)
<br />
#Html.EditorFor(x => x.Sku)
<br/>
#Html.EditorFor(x => x.Title)
...
}
Renaming the Dropdownlist "Category" to = "newItem.Category", did the work, basically if you expect a model to be received in controller, which in this case was "newItem", down control name should match the model name and its property.