maybe it was a simple question but 2 day I worked on it.
it was work for me in another view, but now not work for me
I want show second dropdownlist by change of first but not work how can I resolve that
I use chrome inspect to show
and use debug mode and breakpoints , the debugger didn't go to control
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function() {
$(document).on("change","#ProvinceId",function() {
var pid = this.value;
$.ajax({
type: "POST",
url:'#Url.Action("ReturnCity", "Account")',
dataType:"json",
data:{provinceId:pid},
contentType:'application/json; charset=utf-8',
success: function(data) {
$('#CityId').empty();
$.each(data,
function (index, item) {
$('#CityId').append($('<option></option>').text(item.Name).val(item.Id));
});
}, error: function (data)
{ alert(data) }
});
});
});
</script>
}
and my control is
public ActionResult Register()
{
//return PartialView("_Login");
ViewBag.ProvinceId = new SelectList(_db.Provinces, "Id", "Name");
ViewBag.CityId = new SelectList(_db.Cities, "Id", "Name",_db.Cities.Where(x => x.ProvinceId == 1));
return View("");
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email,CountryId = 55,ProvinceId = model.ProvinceId,CityId = model.CityId};
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
MigrateShoppingCart(model.Email);
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(user.Id, "" + callbackUrl + "\">link</a>");
// Uncomment to debug locally
// TempData["ViewBagLink"] = callbackUrl;
ViewBag.Message = "";
return View("Info");
//return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
for return city this is code in control
[HttpPost]
public JsonResult ReturnCity(int provinceId)
{
_db.Configuration.ProxyCreationEnabled = false;
var data = _db.Cities.Where(x => x.ProvinceId == provinceId);
return Json(data.ToList(), JsonRequestBehavior.AllowGet);
}
in view i use this for show two related dropdownlist
<div class="form-group">
#Html.LabelFor(model => model.ProvinceId, "استان", htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#*#Html.DropDownListFor(model=>model.ProvinceId, (SelectList)ViewBag.ProvinceId, "Select", new { htmlAttributes = new { #class = "form-control" }})*#
#Html.DropDownList("ProvinceId", "Select")
#Html.ValidationMessageFor(model => model.ProvinceId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CityId,"City", htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-8">
#*#Html.DropDownListFor(model => model.CityId, (SelectList)ViewBag.CityId, "Select", new { htmlAttributes = new { #class = "form-control" } })*#
#Html.DropDownList("CityId", "Select")
#Html.ValidationMessageFor(model => model.CityId, "", new { #class = "text-danger" })
</div>
</div>
I see few issues with your code. First, in your ajax call, you specify the contentType contentType:'application/json; charset=utf-8',. But you are trying to send a javascript object in the data property. So jQuery will send Content-Type:application/json; charset=UTF-8 in the request header and provinceId=1 as the request payload in the request body. The server code uses the contentType header to determine how to deserialize and model bind the posted form data/request body to the parameter of your action method. Usually you specify the content type as json when you send a stringified json version of a javascript object. The Model binder will be able to map this to your method param (a view model object matching with the structure of your js object)
Since your method parameter is a simple int, you do not need to specify the contenttype as application/json. Simply remove that line and it will hit the action method in server . You can also remove the datatype param as well.
This should work as long as you do not have any other script error in the page(check browser console).
$(document).ready(function() {
$(document).on("change","#ProvinceId",function() {
var pid = this.value;
$.ajax({
type: "POST",
url:'#Url.Action("ReturnCity", "Account")',
data:{provinceId:pid},
success: function(data) {
$('#CityId').empty();
$.each(data,
function (index, item) {
$('#CityId').append($('<option></option>')
.text(item.Name).val(item.Id));
});
}, error: function (data)
{ alert(data) }
});
});
});
Also since you want user to select the city based on selected province, there is no need to load all cities. You can simply render a select element using vanilla html with Id and Name set to CityId
See this post for some sample cascading dropdown code.
Change your code as following.
Script
#section Scripts {
<script>
$(document).on("change","#ProvinceId",function() {
var pid = this.value;
$.ajax({
url: '/Account/ReturnCity',
type: "POST",
dataType: "JSON",
data: { provinceId: pid },
success: function (data) {
$("#CityId").html(""); // clear before appending new list
$.each(cities, function (i, city) {
$("#CityId").append(
$('<option></option>').val(city.CityId).html(city.CityName));
});
}
});
)}
</script>
}
Controller
public ActionResult ReturnCity(int provinceId)
{
_db.Configuration.ProxyCreationEnabled = false;
var data = _db.Cities.Where(x => x.ProvinceId == provinceId);
return Json(data , JsonRequestBehavior.AllowGet);
}
Related
I have a small view inside of an HTML.Action that lives inside my _Layout. I am trying to send the ProjectId of the selected project to the Create Ticket View. My modal view looks like this.
Here is the controller method for the modal view:
[AllowAnonymous] // Change this to only submitters
public ActionResult NavRoleItems()
{
ViewBag.ProjectId = new SelectList(db.Projects, "Id", "Name");
return View();
}
Modal View
#using (Html.BeginForm("Create", "Tickets", FormMethod.Get))
{
#Html.AntiForgeryToken()
<div class="modal-body">
#Html.DropDownListFor(p => p.ProjectId, null, new { #class = "form-control"})
</div>
<div class="modal-footer">
<input type="submit" value="Add Issue" />
</div>
}
And I want to send any way I can really, but Ideally I want to send it as the projId variable below. Im in school and this is the first time I have played with Formmethod.Get.
Controller View
public ActionResult Create(string projId)
{
TicketCreateViewModel model = new TicketCreateViewModel();
var userId = User.Identity.GetUserId();
var user = db.Users.Find(userId);
model.OwnerUserId = userId;
model.OwnerUser = user;
model.ProjectId = projId;
model.AssignedToUserId = new SelectList(db.Users, "Id", "FirstName");
ViewBag.TicketPriorityId = new SelectList(db.TicketPriorities, "Id", "Name");
ViewBag.TicketStatusId = new SelectList(db.TicketStatuses, "Id", "Name");
ViewBag.TicketTypeId = new SelectList(db.TicketTypes, "Id", "Name");
return View();
}
Every way that I have tried it, html hidden and as a param in the begin form, doesn't work because it sees the #Model.ProjectId as null when it loads. As it should bc it is null. But how can I tell it to send it to the Create Tickets controller after the user selects and hits submit?
First Change This in your view
#Html.DropDownListFor(model => model.ProjectId, new SelectList(ViewBag.ProjectId , "Value", "Text"), "...", htmlAttributes: new { #class = "form-control" })
Change your controller variable name by ProjectId
It might Work fine
Another Way
You can add onclick in your button
function submitForm()
{
$.ajax(
{
url: 'Url',
type: "GET",
contentType: "application/json",
data: JSON.stringify({projId: $('ProjectId').val()}),
success: function(objStatus) {},
error: function(xhr, status, error)
{
if(status === "timeout")
{
alert(msg_timeout);
}
else
{
alert(msg_error);
}
},
});
}
why you set null the feeder argument of dropDownListFor ?
set with ViewBag.ProjectId content instead of null
Or
you can fill the viewbag with projects data and in view
do like this :
Controller
[AllowAnonymous]
public ActionResult NavRoleItems()
{
ViewBag.Projects = db.Projects;
return View();
}
View
add a model top of the page that it has ProjectId property
#Html.DropDownListFor(x => x.ProjectId, new SelectList(ViewBag.Projects, "Id", "Name"))
change Create action argument to type that insert top of the view
I have a view that has a dropdown that is generated by a linq statement when the view is populated.
<div class="form-group">
#Html.LabelFor(m => m.OrderID, "Order ID")
<div>
#Html.DropDownListFor(m => m.OrderID, Model.Orders, "Select Order ID",
new { #id = "orderDropdown" })
</div>
</div>
I have 2 other fields in the view that need to be updated with the data retrieved from the database.
<div class="form-group">
#Html.Label("Final Weight")
<div id="finalWeight">
#Html.DisplayFor(m => m.FinalWeight)
</div>
</div>
<div class="form-group">
#Html.Label("Initial Weight")
<div id="initialWeight">
#Html.DisplayFor(m => m.InitialWeight)
</div>
</div>
This is the ajax that I got from the link below:
<script>
$("#orderDropdown").change(function (event) {
$.ajax({
url:"???" + $(this).val(),/* not sure what to use*/
data: { id: $(this).val()},
cache: false,
type: "GET",
dataType: "html",
success: function (data, textStatus, XMLHttpRequest) {
$("#divinitialWeight").html(data);
}
});
});
Here is the controller code
[HttpGet]
[OpenAction]
public async Task<float> GetInitialWeight(int sid)
{
var initialWeight = await Manager.FindInitialFilterWeightBySID(sid);
return initialWeight.MeanWeight;
}
The method is in a Data Access Layer that is only referenced in the main project. The way I would call it in the controller would be like below and pass it the orderId :
Entities.Manager.FindInitialWeight(orderId);
Entities.Manager.FindFinalWeight(orderId);
I came across this SO question and it's close to what I need but the only issue is the url: because the data retrieval method is not in my controller...it is in the data access layer that is only a reference. Also the orderId is being passed as a parameter.
How can I call that method from ajax and pass it the orderId from the url: of the ajax call?
You can call the controller method from JQuery like this
if the JQuery code is within the razor view
url: '#Url.Action("GetInitialWeight")',
data: { sid: $(this).val()},
I actually had to create a GET method in my controller that contacted the DAL with the passed parameter from the javascript
[HttpGet]
[OpenAction]
public async Task<ActionResult> GetInitialWeight(int sid)
{
var initialWeight = await Manager.FindInitialFilterWeightBySID(sid);
return Json(new { initialWeight.MeanWeight }, JsonRequestBehavior.AllowGet);
}
Then change the javascript as such
<script>
$("#sidDropdown").change(function (event) {
var url = "/Controller/GetInitialWeight/";
var data = { sid: $(this).val() };
var dataType = "json";
$.get(
url,
data,
function (response) {
$("div#initialWeight").text(response.MeanWeight)
console.log(response.MeanWeight);
}, dataType);
});
Note : I'm new to MVC
In my case it has two views and two controllers.I am passing selected item value to the the second controller from first view using ajax.passing is success.
but when second view appears , the value is null.Is this ajax problem or mvc. I can't understand.
this is my first controller and first view
public ActionResult First()
{
//get the location data
var Loc = getData("Location", "", "", "");
List<Firstdata> llc = new List<Firstdata>();
foreach (var val in Loc)
{
llc.Add(new Firstdata
{
Destination =val
});
}
ViewBag.Loc = llc;
return View();
}
first view
<div class="col-md-6 form-group">
<label>Destination</label>
<select class="form-control" id="destination">
#foreach (var item1 in #ViewBag.Loc)
{
<option>#item1.Destination</option>
}
</select>
</div>
<div class="clearfix"></div>
<div class="form-group">
<div class="btn" id="bud">
#Html.ActionLink("GO", "Check","Cruise")
</div>
</div>
ajax passing in first view
<script type="text/javascript">
$("#bud a").click(function () {
var destination = $("#destination").val();
$.ajax({
url: '#Url.Action("Check","Cruise")',
data: { 'destination': destination },
type: "POST",
dataType: "XML",
//contentType: "application/xml",
async: true,
success: function(data){
if (!data)
alert("no xml data returned");
else {
alert("success");
}
//location.href = "~/Views/Cruise/Check.cshtm";
}
});
});
</script>
this is my second controller
public ActionResult Check(string destination)
{
XElement rootele = XElement.Load(Server.MapPath("~/XmlFiles/CruiseData/cruiseprodutstwo.xml"));
var getneededData = rootele.Elements("CruiseProduct")
.Where(l => l.Element("Location").Value == destination)
.Select(s => s.Element("Name").Value);
List<Details> d = new List<Details>();
foreach(var itm in getneededData)
{
d.Add(new Details
{
cruiseName = itm
});
}
ViewBag.needed = d;
return View();
}
** In this point destination is not null and d(ViewBag.needed) is also not null.it shows the count
this is my second view
<div>
#foreach (var itme in #ViewBag.needed)
{
<h2>#itme</h2>
}
</div>
in here loop go through for #ViewBag.needed count and finally display null.no idea what is going.
please help me with this.
I think there is a routing problem there. If you are using default routing that is
routes.MapRoute(name:"Default",
url:"{controller}/{action}/{id}",
defaults:new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
then you need to chagne controller parameter name destination to id
as:
public ActionResult Check(string id)
{
and in JQuery call change it as
$.ajax({
url: '#Url.Action("Check","Cruise")',
data: { 'id': destination },
Or
you can add new route in RouteConfig.cs as
routes.MapRoute(name:"Default",
url:"{controller}/{action}/{destination}",
defaults:new { controller = "Cruise", action = "Check" }
);
For routing you can refer to http://www.niceonecode.com/Q-A/DotNet/MVC/routing-in-mvc-4/20190
I am loading partial view with Jquery UI dialog. In partialview post submit I want capture results in updateSuccess function. But function was never called and results was showing on page.
Parent page
<script type="text/javascript">
function display_dialog() {
$('#my-dialog').dialog({
resizable: false,
modal: true,
show: "blind",
hide: "blind",
open: function (event, ui) {
$(this).load("/ContactSubmission/Index" );
}
});
function updateSuccess(data) {
if (data.Success == true) {
alert("Inside Update");
//now we can close the dialog
$('#my-dialog').dialog( "close" );
//twitter type notification
$('#commonMessage').html("Update Complete");
$('#commonMessage').delay(400).slideDown(400).delay(3000).slideUp(400);
} else {
$("#update-message").html(data.ErrorMessage);
$("#update-message").show();
}
}
</script>
controller
public ActionResult Index()
{
var contact = new Contact
{
Countries = Context.GetCountries()
};
return PartialView(contact);
}
[HttpPost]
public JsonResult Index(Contact contact)
{
if (ModelState.IsValid)
{
if (contact != null)
{
//Some business logic is here
var result = new { Success = "True", Message = "No Error" };
return Json(result, JsonRequestBehavior.DenyGet);
}
else{
var result = new { Success = "False", Message = "Contact is Null" };
return Json(result, JsonRequestBehavior.DenyGet);
}
}
else
{
var result = new { Success = "False", Message = "Invalid state" };
return Json(result, JsonRequestBehavior.DenyGet);
}
}
Partial view
#using (Ajax.BeginForm("Index", "ContactSubmission", new AjaxOptions{
InsertionMode = InsertionMode.Replace, HttpMethod = "POST",
OnSuccess = "updateSuccess" },new { enctype = "multipart/form-data",
#class = "form-horizontal", role = "form" }))
{
// Html code is here
<div class="form-group">
<div class="col-sm-4 col-md-offset-5">
<button type="submit" class="btn btn-primary">Submit</button>
<button type="button" class="btn btn-default" id="cancel">Cancel
</button>
</div>
</div>
}
after submit is showing like this on browser
How can I handle the issue and how to call function after submit results?
You need to reference jquery Unobtrusive otherwise the view will change.
http://www.nuget.org/packages/jQuery.Ajax.Unobtrusive/
This has caught me out before and as a result I find it much easier to write my own ajax calls in jQuery so I dont need this reference.
Good Luck
In the code below, I have a form with some informations about an employee. I'd like feel in the password and post. If the password is correct the user is redirected to /Dashboard that it's ok.
When the password is wrong, I'd like show the error (_ErrorPartial) in MyError div and still see the form. I'd like see the form and the message in the div (MyError). With the code below, when the password is wrong, I see the error message but on a blank page and not a page with the layout + the form + the error message
Any idea ?
Thanks,
My page :
#model MyApp.EmployeeModel
<script type="text/javascript">
$(document).ready(function () {
$(".").click(function () {
$.ajax({
url: '/Account/Login',
type: "Post",
data: $('#MyForm').serialize(),
success: function (result) {
alert('Im here');
$("#MyError").html(result);
//Here is code to detect error or not but removed
}
});
});
});
</script>
<div id="MyError"></div>
#using (Html.BeginForm("Login", "Account", FormMethod.Post, new { id = "MyForm" }))
{
#Html.AntiForgeryToken()
<div>
#Html.LabelFor( m => m.FirstName)
<div>
#Html.HiddenFor(model => model.Username)
#Html.LabelFor( m => m.Password)
#Html.PasswordFor(m => m.Password)
<input type="submit" class="jqClick" />
</div>
</div>
}
Controller :
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(EmployeeModel employeeModel)
{
var Errors = new List<string>();
var employee = .... //Get employee from DB
if (employee == null)
{
Errors.Add("Employee trouble");
return PartialView("_ErrorPartial", Errors.AsEnumerable());
}
return RedirectToAction("Index", "Dashboard");
}
My _ErrorPartial view :
#model IEnumerable<string>
<div id="DisplayError">
#{ var error = string.Empty; }
#foreach (var err in Model){
error += err + "<br>";
}
#Html.Raw(error)
</div>
You have to make some changes to your javascript code. First of all, replace jQuery selector $(".") with specific one, like $(".jqClick"). Second of all, never hardcode urls like /Account/Login in your code, use UrlHelper for that. And the third thing is, you have to prevent a default behavior of the submit button. See the changes:
$(document).ready(function () {
$(".jqClick").click(function (e) {
e.preventDefault();
$.ajax({
url: '#Url.Action("Login", "Account")',
type: "Post",
data: $('#MyForm').serialize(),
success: function (result) {
alert('Im here');
if (result.redirectUrl)
window.location.href = result.redirectUrl;
else
$("#MyError").html(result);
//Here is code to detect error or not but removed
}
});
});
});
Also you need to change the Login action a little in order to make a redirect if a login is success:
public ActionResult Login(EmployeeModel employeeModel)
{
var Errors = new List<string>();
var employee = .... //Get employee from DB
if (employee == null)
{
Errors.Add("Employee trouble");
return PartialView("_ErrorPartial", Errors.AsEnumerable());
}
return Json(new { redirectUrl = Url.Action("Index", "Dashboard") });
}
The probable error that you throw from the server side, won't appear in success function. Instead you should have below
error:function(response)
{
//your code here
}
Simply throw exception from the controller.