I'm using Html.Beginform in view page and get the parameters using FormCollection to the controller i want to return the Success message on the same ViewPage as a result.i'm using following code,
public string InsertDetails(FormCollection collection)
{
string result = "Record Inserted Successfully!";
return result;
}
It shows the success message on the new page.How can i resolve this? what i have to return to get the Success message on the same page?
Personally, I'd pop the result string into the ViewBag.
public ActionResult InsertDetails(FormCollection collection)
{
//DO LOGIC TO INSERT DETAILS
ViewBag.result = "Record Inserted Successfully!";
return View();
}
Then on the web page:
<p>#ViewBag.result</p>
I have following Options.
1. Use Ajax Begin Form with AjaxOptions like below
#using (Ajax.BeginForm("ActionName", "ControllerName", new { area = "AreaName" }, new
AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "alert('Success');" //This will execute once the Ajax call is finished.
}, null))
{
<input type="submit" name="nameSubmit" value="Submit" />
}
2. Use JQuery to Manually Setup the XHR Request
$.ajax({
url: "#Url.Action("ActionName", "ControllerName", new { area = "AreaName" });",
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({param : Value})
})
.done(function () { alert('Success');}) //This will execute when you request is completed.
.fail(function () { })
My Suggestions
There are following disadvantages while using the FormCollection
Point - 1
In case FormCollection is being used...It will be mandatory to Type Cast the Primitive Type Values un-necessarily because while getting the entry of specific Index of the System.Collections.Specialized.NameValueCollection, value being returned is of type String. This situation will not come in case of Strongly Typed View-Models.
Issue - 2
When you submit the form and goes to Post Action Method, and View-Model as Parameter exists in the Action method, you have the provision to send back the Posted Values to you View. Otherwise, write the code again to send back via TempData/ViewData/ViewBag
Point - 3
We have Data Annotations that can be implemented in View Model or Custom Validations.
ASP.Net MVC simplifies model validatons using Data Annotation. Data Annotations are attributes thyat are applied over properties. We can create custom validation Attribute by inheriting the built-in Validation Attribute class.
Point - 4
Example you have the following HTML
<input type="text" name="textBox1" value="harsha" customAttr1 = "MyValue" />
Question : How can we access the value of customAttr1 from the above eg from inside the controller
Answer : When a form get posted only the name and value of elements are posted back to the server. You can also use Hidden Fields to post the Attributes to Post Action method.
Alternatives : Use a bit of jQuery to get the custom attribute values, and post that along with the form values to action method
Another option is to rather put what you got in your custom attributes in hidden controls
That's the reason, I would always prefer to use View-Models
we can do it on Form inside view
#using (Ajax.BeginForm("Action", "Controller", new AjaxOptions { HttpMethod = "POST", OnSuccess = "Showmessage" }))
[HttpPost]
public ActionResult Test(TestViewModel model)
{
return Json(new {isok=true, message="Your Message" });
}
function Showmessage(data)
{
$('#Element').html('Successfully Submitted');
}
Related
I have some checkboxes and a button (not in a form).
When the button is clicked, I have some jQuery and I am creating a post model which contains the values of the checked boxes and posting to a controller.
The controller then creates view models and I want to redirect the user to the correct view, passing the view model in to the view.
jQuery:
$.ajax({
url: AppSettings.baseUrl + "BOM/getMultiBOM",
type: 'POST',
data: JSON.stringify(data)
});
Controller:
[HttpPost]
public ActionResult getMultiBOM(multiBOMPostModel multiBomsPostModel)
{
BOM bom = null;
foreach (int value in multiBomsPostModel.bomsArray)
{
bom = db.BOMs.Find(value);
}
BOMViewModel viewModel = getViewModel(bom, null);
return RedirectToAction("OpenMultiBOM", new { viewModel = viewModel, bom = bom });
}
public ActionResult OpenMultiBOM(BOMViewModel viewModel, BOM bom)
{
viewModel.projectModel = new ProjectViewModel
{
project = bom.Project
};
return View(viewModel);
}
It is probably a bit of a mess.
I think the jQuery is necessary to pass the checkbox values to the controller.
When I use RedirectToAction to the method which then returns the view, the model is not being passed through, presumably as it is sending the model as a query string.
The view model is not simple and contains lists, IEnumerables, and nested models.
Can anyone help with the most efficient way to redirect/return the view while passing the view model?
Answer: I kept the ajax to post my checkbox values to the controller
$.ajax({
url: AppSettings.baseUrl + "BOM/getMultiBOM",
type: 'POST',
data: JSON.stringify(dataArr),
}).done(function (result) {
location.href = "/BOM/OpenMultiBOM";
});
In my controller, I assigned the posted values to a postModel and then stored them in TempData. The key here was to return a Json value which would then allow the redirect on the client side to take place.
public ActionResult getMultiBOM(multiBOMPostModel multiBOMPostModel)
{
TempData["BOMs"] = multiBOMPostModel;
return Json("success");
}
I then had another HttpGet method which would load after the page is redirected by the Ajax result and cast the TempData to an object.
[HttpGet]
public ActionResult OpenMultiBOM(int? BomMarkupMessage = null)
{
var bomIds = TempData["BOMs"] as multiBOMPostModel;
}
I would persist the viewmodel server side, perhaps in a session variable, or perhaps as a TempData (TempData typically only lives until the next request), and pass a key for the session variable to the second controller in the case of session variable, or use the TempData directly in your view in the case of TempData. This would avoid passing the whole object back and forth multiple times.
So the way that i have done this before is to have an empty div in DOM.
<div id="partialViewContent">
<!-- Content will be loaded later. -->
</div>
If you have a default view, you'll need to set it to load from URI using the below snippet.
$("#partialViewContent").load("Controller/Action",
function (response, status) {
if (status !== "success") {
console.log("An error has occured when attempting to load partial view.");
}
});
When you post to your controller action via JQUERY, have the action return a partial view with the model. (Assume model is relevant to each partial view).
Then when your ajax is complete, replace the content in partialViewContent with the POST response.
How to pass jQuery variable value to c# mvc ?
I need to fetch the value of the variable btn in mvc code behind.
$('button').click(function () {
var btn = $(this).attr('id');
alert(btn);
$.ajax({
type: 'GET',
url: '#Url.Action("ActionName", "ControllerName")',
data: { id: btn },
success: function (result) {
// do something
}
});
});
Based on the variable value (Submit Button (or) Preview Button), my model will have Required validation on certain fields.
In my controller , i am calling as
[HttpGet]
public ActionResult ActionName(string id)
{
var vm = id;
return View(vm);
}
Though , ActionResult in controller is not invoked.
Jquery : alert(btn); -- is calling. I can see the alert window showing with the id. However, I am not able to retrieve the id in the controller.
You need to use jQuery.ajax() (or its shortened form jQuery.get()/jQuery.post()) with GET/POST method and set up a controller action with an argument to pass button ID:
jQuery (inside $(document).ready())
$('button').click(function () {
var btn = $(this).attr('id');
var url = '#Url.Action("ActionName", "ControllerName")';
var data = { id: btn };
// if controller method marked as POST, you need to use '$.post()'
$.get(url, data, function (result) {
// do something
if (result.status == "success") {
window.location = '#Url.Action("AnotherAction", "AnotherController")';
}
});
});
Controller action
[HttpGet]
public ActionResult ActionName(string id)
{
// do something
return Json(new { status = "success", buttonID = id }, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult AnotherAction()
{
// do something
return View(model);
}
If you want to pass retrieved button ID from AJAX into other action method, you can utilize TempData or Session to do that.
It is a nice coincidence that you use the word "fetch" to describe what you want to do.
jQuery runs in the browser as a frontend framework. Meaning that it runs on the client`s computer. Your MVC-C#-Code lies on the server. Therefore, if you want to send data between those two computers, you need to use the http protocol.
1. Ajax and REST:
Using an ajax call using http methods (post or put) to push your variable value as JSON to the backend`s REST api (route).
For this option, you might want to have a look at the fetch function of javascript.
2. HTML Forms
Use a html form where you store the variable value inside one input element. A form submission will perform a http post (by default) request to the backend as well and use all input element values as post parameters.
There are many ways to accomplish what you are looking to do, but I'll stick to using your code sample.
So what you need to do is utilize the .ajax call in jquery to send data from your view to your controller. More on that here: http://api.jquery.com/jquery.ajax/
Using your code, you'd put the .ajax call within your logic flow of what to do based on which button is clicked.
$("button").click(function ()
{
var btn = this.id;
if (btn == "previewButton")
{
$.ajax({
url: "/MyApp/MyAction",
type: "POST",
data: { btnId: btn },
dataType: "json",
async: true,
cache: false
}).success(function(data){
// do something here to validate if your handling worked
}).error(function(){
// Do something here if it doesnt work
});
}
}
You'll see that there is a URL. In my example i've chose MyApp as my controller and MyAction as the method of the controller in which we are posting values to. The ajax call posts 1 parameter with a property of btnId. If you need to pass more data, the property name in the jquery call should correspond with an argument of the actions method signature within the controller.
So my controller looks like
public MyAppController : Controller
{
[HttpPost]
public JsonResult MyAction(string btnId)
{
Debug.WriteLine("btnId: {0}", btnId);
return Json(new{ ButtonId= btnId });
}
}
This would be one way to handle passing values from your view to your controller using .ajax calls with jquery.
My preferred way is to use the Html helpers of Ajax.BeginForm which could be another option for you.
https://www.aspsnippets.com/Articles/ASPNet-MVC-AjaxBeginForm-Tutorial-with-example.aspx
So basically I'm trying to show some Profile Data in my MVC Application.
Right now, everytime I click on a date on my Telerik Kendo Calendar, I can refresh the whole page and update the data I want.
However, instead of refreshing the whole I just want to refresh the partial views that shows only the data that updates after selecting the date.
Index.cshtml
<!--CODE-->
#Html.Partial("_WorkingTimeData")
<!--CODE-->
_WorkingTimeData.cshtml
var workedTime = ViewData["WorkedTimeToday"];
var hoursPerDay = ViewData["HoursPerDayContract"];
<p>You worked #workedTime hours</p>
<p>Hours Per Day (Contract) #hoursPerDay Hours</p>
Yes, right now I'm ViewDatas and it works.
This is the ajax code in Index.cshtml
$.ajax({ url: '/Profile/Index',
dataType: "json",
type: "POST",
data: JSON.stringify(10),
success: function(returl){
alert('It worked');
location.href=returl.Url;
},
error: function(jqXHR,responseText,textStatus){ alert(jqXHR.responseText) } });
Controller
[HttpPost]
public ActionResult Index(string number){
//THINGS TO DO
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Profile");
return Json(new { Url = redirectUrl });
}
Well I'm very new to this, and I've been doing my research. However I still have some questions:
- Do I need to create a post method for _WorkingTimeData instead of Index like I have?
- Do I need to create a ViewModel for the Partial View?
Thanks
EDIT NUMBER 2 FOR VISHAL:
This didn't work at all, not even an alert, because, strangely, it doesn't recognise the calendar...
$("#calendar").kendoCalendar({
change : function() {
$.ajax({
url: "/Profile/WorkingTimeData",
type: "get"
}).done(function(data) {
$("#profile-timeline").html(data);
});
}});
It says $("#calendar").kendoCalendar is not a function (Telerik says that it's this way)
As for this, it reached the controller but didn't update anything:
function change() {
alert("Escolheste outro dia");
var calendar = $("#calendar").data("kendoCalendar");
var current = calendar.current();
alert(current);
$.ajax({
url: "/Profile/WorkingTimeData",
type: "get"
}).done(function(data) {
$("#profile-timeline").html(data);
});
}
I think it's because of the profile-timeline... It's a div in my view
Do I need to create a post method for _WorkingTimeData?
Yes, you need to create. But, Get would be fine too.
Do I need to create a ViewModel for the Partial View?
Not needed. If required you can create.
But, by looking at your partial view you are just using ViewData[""]. So, you need not to create any ViewModel.
Just create a method in Controller returning _WorkingTimeData PartialView.
And call that method by JQuery ajax on your DatePicker change event and replace the contents of the Div.
For example.
Controller
public PartialViewResult WorkingTimeData()
{
ViewData["WorkedTimeToday"]="NEW VALUE";
ViewData["HoursPerDayContract"] = "NEW VALUE";
return this.PartialView("_WorkingTimeData");
}
JavaScript
$("DATEPICKERELEMENT").change(function() {
$.ajax({
url: "/CONTROLLER/WorkingTimeData",
type: "get"
}).done(function(data) {
alert(data);
$("#divisionIdContainingPartialView").html(data);
}).fail(function() {
alert('error');
});
});
I wrote a post that details why you need to break the logic of thinking about partial views client-side. If you're interested you can find it here.
The TL;DR version is simply, all you have client-side is HTML. There's no knowledge about what was or was not rendered to the response via a partial view. As a result, the real question is "How do I change a portion of my HTML page based on an AJAX response?". In the simplest form, you simply select some element on the page and then alter its inner HTML. You can do that with some custom HTML created client-side or you can actually pass back an HTML document as your AJAX response and then insert that.
I reallly have a simple set of code to bring back a set of data that is triggered off a drop down.
this is the script:
function () {
$('#ProviderID').change(function () {
$.ajax({
url: '/servicesDisplay/Index',
type: 'Get',
data: { id: $(this).attr('value') },
success: function (result) {
// The AJAX request succeeded and the result variable
// will contain the partial HTML returned by the action
// we inject it into the div:
$('#serLocations').html(result);
}
});
});
This is the controller:
public ActionResult Index(string id)
{
int prid = Int32.Parse(id.Substring(0, (id.Length-1)));
string mulitval = id.Substring((id.Length-1), 1).ToString();
System.Data.Objects.ObjectResult<getProviderServiceAddress_Result> proList = theEntities.getProviderServiceAddress(prid);
List<getProviderServiceAddress_Result> objList = proList.ToList();
SelectList providerList = new SelectList(objList, "AddressID","Address1");
//ViewBag.providerList = providerList;
return PartialView("servicesDisplay/Index", providerList);
}
This is the view:
#model OCS_CS.Models.servicesDisplay
<div>
#Html.DropDownList(model => model.ServiceAdderssID, (IEnumerable<SelectListItem>)model)
</div>
When the drop down passes the in the value. The apps does hit the controller. But it highlightes the drop down in a light red and the view never displays.
Try this short version which uses the jquery load method.
$(function(){
$('#ProviderID').change(function () {
$('#serLocations').load("#Url.Action("Index","ServicesDisplay")?id="
+$(this).val());
});
});
If you want to avoid caching of result, you may send a unique timestamp along with the querystring to avoid caching.
$('#serLocations').load("#Url.Action("Index","ServicesDisplay")?id="
+$(this).val()+"&t="+$.now());
You are doing a GET, thats no meaning to pass data to ajax, you may pass data for POST:
First, put the value at the URL:
function () {
$('#ProviderID').change(function () {
$.ajax({
url: '/servicesDisplay/Index/' + $(this).attr('value'),
type: 'Get',
success: function (result) {
// The AJAX request succeeded and the result variable
// will contain the partial HTML returned by the action
// we inject it into the div:
$('#serLocations').html(result);
}
});
});
Second, mark the method as GET
[HttpGet]
public ActionResult Index(string id)
Hopes this help you!
You have quite a few problems with your code. First the model defined for your view is:
#model OCS_CS.Models.servicesDisplay
but in your action your're invoking the call to this view by passing in a SelectList:
SelectList providerList = new SelectList(objList, "AddressID","Address1");
return PartialView("servicesDisplay/Index", providerList);
this is not going to fly because the models do not match by type. Seconds problem is you are casting this SelectList into an IEnumerable. This is also not going to work. You need to cast to SelectList:
#Html.DropDownList(model => model.ServiceAdderssID, (SelectList)model)
but again until you match the type of your model in your action with the model on your view none of this will work. I suggest you install Fiddler to help you determine what sort of error are you getting.
firs of all i searched for my question but couldnt find anything that helped me get any further.
i am trying to implement a view which allows me to set permissions for the current user.
As the data-structure i use following recursive class where each PermissionTree-Object references the sub-permissions (permissions are hierarchically structured in my application) :
public class PermissionTree
{
public Permission Node; //the permission object contains a field of type SqlHierarchyId if that is relevant
public bool HasPermission;
public IList<PermissionTree> Children;
//i cut out the constructors to keep it short ...
}
here is how the controller looks like:
//this is called to open the view
public ActionResult Permissions()
{
//pass the root element which contains all permission elements as children (recursion)
PermissionTree permissionTree = PopulateTree();//the fully populated permission-tree
return View(permissionTree);
}
//this is called when i submit the form
[HttpPost]
public ActionResult Permissions(PermissionTree model)
{
SetPermissions(model);
ViewData["PermissionsSaved"] = true;
return View(model);//return RedirectToAction("Index");
}
in am using a strongly typed view like this:
#model PermissionTree
//....
#using (Html.BeginForm("Permissions", "Permission", null, FormMethod.Post, new { #class = "stdform stdform2" }))
{
<input name="save" title="save2" class="k-button" type="submit" />
<div class="treeview">
//i am using the telerik kendoUI treeview
#(Html.Kendo().TreeView()
.Name("Permissions")
.Animation(true)
.ExpandAll(true)
.Checkboxes(checkboxes => checkboxes
.CheckChildren(true)
)
.BindTo(Model, mapping => mapping
.For<PermissionTree>(binding => binding
.Children(c => c.Children)
.ItemDataBound( (item, c) => {
item.Text = c.Node.PermissionName;
item.Checked = c.HasPermission;
})
)
)
)
ok, so when i click the button, i want my viewmodel to be sent to the controller action that is decorated with [HttpPost]. But when i debug the application, the received model does not really contain my data (it is not null though).
Does anyone know how i can achieve my goal and get the whole viewmodel?
best regards,
r3try
I think it's better to use a JSON post here ,then it's easy to prepare the object in the javascript side.
I don't know how your HTML looks like or the names of the elements you can easyly use javascript/Jquery to build the client side json object with similar names and slimier hierarchy/dataTypes just like in the PermissionTree class. And then use Ajax post to post as JSON
var PermissionTree={Node:{},HasPermission:false,Children:{}}
$.ajax({ data:PermissionTree
type: "POST",
url: 'YourController/Permissions',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
}
);
The important thing is you need to find a better way of going throuth the tree view and build the object in javascript.
as i cant get that to work i was trying a slightly different approach:
example for adding a node:
- press add button -> execute ajax call -> add the node in nhibernate -> call the view again with the new data (the new node included)
controller-action that is called by the ajax request:
[Authorize]
[HttpPost]
public ActionResult AddPermission(string parentPermissionName, string permissionName)
{
var pd = ServiceContext.PermissionService.permissionDao;
Permission parentPermission = pd.GetPermissionByName(parentPermissionName);
if (parentPermission == null) {
parentPermission = pd.GetRoot();
}
if (parentPermission != null && !string.IsNullOrEmpty(permissionName) && !pd.PermissionExists(permissionName))//only add with a name
{
pd.AddPermission(parentPermission, permissionName);
}
//refresh data
PermissionTree permissionTree = LoadTreeSQLHierarchy(null, false);//start at root
return View("Permissions", permissionTree);
}
Ajax Request in the View:
function addNode() {
//... get the data here
var addData = { parentPermissionName: selectedNodeName, permissionName: newNodeName };
$.ajax(
{
data: addData,
type: "POST",
url: '#Url.Action("AddPermission", "Permission")',
dataType: "json",
success: function (result) {
//$('.centercontent').html(response);//load to main div (?)
return false;
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status + ":" + thrownError);
return false;
}
}
);
return false;
}
But when i execute this i get an error stating that json.parse hit an invalid character (i get this error at the alert in the ajax's error function).
Judging from that message i would say that the problem is that i am returning html but the ajax call expects json or so...
But what is the correct way to just reload my view with the new data? Can i somehow tell the ajax call to not go back at all and just execute the called controller-method?