I making a .Net web app using a third party gridview(DevExpress web form ASPxGridView).
Lets say I have two grids(Grid1 and Grid2, both devexpress).
I am running into an issue where I need to update values in Grid2 based on which column is clicked on Grid1(during the onClick event).
I am able to capture the row and column in JavaScript but am not able to pass it back to my serverside code.
The grid has some settings tied to the edit mode, that if the page does a full postback, the grid loses its edits.
I have tried setting a HiddenField and calling a postback, but that erases edits in my grid. I have tried passing the variables to a static method , but I cannot access the controls on my page to update Grid2. I have looked into trying to do a callback instead of a postback, but it looks like callbacks are referencing Client-Side methods.
Does any one know of a way to pass a client-side variable to c# without a postback, or to call a non-static c# method from JavaScript? Any suggestions would be greatly appreciated.
The most basic approach to do this would involve two parts, part 1) add an ajax js function on your your existing grid page to handle the click event and make the data request. Part 2) Code up a separate C# web page to receive your client-side Grid1-variable, process it accordingly, and then respond with the data for Grid2. Here's some pseudocode of what the ajax call might look like, hope it helps.
//in your javascript section
$("#Grid1Cell").click(function(){
$.ajax({
type: "GET",
url: '#Url.Action("GetGrid2Data", "SomeController")"?yourVar=' + encodeURI(yourVal),
//alternatively url: "yourNonMVCpage.aspx?yourVar=" + encodeURI(yourVal),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
if (response.SomeValues == "blah") {
$("#Grid2Cell").text(response.SomeValues); //update Grid2
}
}});
});
If you need to "connect c#", it is necessary to perform a request to the server (using any of the available techniques - callback, postback, etc.).
If you need to refresh another control (Grid2) rendering during this request, the corresponding HTML content should be returned as a results of this request.
According to the provided description, you need to implement "cascaded grids" - i.e., update a dependent grid when changing a main grid. If so, use the approach illustrated in the https://github.com/DevExpress-Examples/how-to-show-detail-information-in-a-separate-aspxgridview-e70 example and force the dependent grid custom callback (and further refreshing) via the client-side PerformCallback method + handle the server-side CustomCallback event.
Related
I am on Linux -both browser side & server side- with a recent Firefox 38 or 42 if that matters; this question gives more context, and the github GPLv3 project containing my code. It is not a usual Web application (it would have usually one, and perhaps a dozen, of simultaneous Web users). I am writing or generating both server & browser side code
Let's suppose I have some HTML5 code like
<div id="mydyndiv_id"></div>
I am making an AJAX request with JQuery. On success it should insert some (AJAX generated) HTML element, e.g. <b>bold</b> (in reality it is a much bigger HTML fragment with nested <span>-s whose content is dynamically generated from the POST argument of the AJAX request), into that div and call some other Javascript function doit, e.g. doit(42) only once just after the AJAX request (e.g. that function would clear some other <textarea> in my page, and the 42 argument is provided by the AJAX response). I can change code both on server side (e.g. alter the AJAX processing) and on browser side.
What is the most idiomatic way to achieve that?
making a JSON AJAX which contains both the inserted HTML & the function argument, so the AJAX response could be {"text":"<b>bold</b>", "data": 42}" of Content-type: "application/json" and the Javascript code would be
$.ajax
({url: "/someajax",
method: "POST",
data: {"somearg": "foo"},
datatype: "json",
success: function(jsa) {
$("#mydyndiv_id").html(jsa.text);
doit(jsa.data);
}});
this is rather heavy, the server should double-encode HTML&JSON the HTML fragment: it needs first to construct the <b>bold</b> fragment -with HTML encoding, and then to construct the JSON object and send it.
making an HTML AJAX which has some <script> element. The AJAX response would be of Content-type: text/html and would contain <b>bold</b><script>doit(42)</script>, and the Javascript code would be
$.ajax
({url: "/someajax",
method: "POST",
data: {"somearg": "foo"},
datatype: "html",
success: function(ht) {
$("#mydyndiv_id").html(ht);
}});
this might be wrong, since the doit(42) function could be perhaps called more than once and is kept in the DOM and I don't want that
making a Javascript AJAX; the AJAX response would be of Content-type: application-javascript and would contain:
$("#mydyndiv_id").html("<b>bold</b>");
doit(42);
with the AJAX invocation in Javascript being
$.ajax
({url: "/someajax",
method: "POST",
data: {"somearg": "foo"},
datatype: "script",
success: function(jscode) { /* empty body */ }
})
This is brittle w.r.t. errors in doit(42) (see this question; the only debugging technique I found is lots of console.log and that is painful) and also requires double encoding on server side.
Of course, any other technique is welcome!
PS. If you are curious, the code is commit a6f1dd7514e5 of the MELT monitor (alpha stage) and you would try the http://localhost.localdomain:8086/nanoedit.html URL in your browser; this software (which is also a specialized HTTP server!) would have only very few simultaneous Web users (usually one, perhaps a dozen); in that sense it is not a usual web application. In my dreams it could become a workbench for a small team of (C & C++) software developers, and the GUI of that workbench would be their browser.
These different approaches have pros and cons, but generally the first two options are more advisable, let's see:
JSON AJAX
First of all, working with templating on your server is the right approach. If you use this method you will be able to pass more flexible data from your server to your client as you can e.g. use {"text":"<b>bold</b>", "data": 42, "more_data": 43}".
You are not bound to use just the data at the moment you initially create the service but expand passed data easily.
HTML AJAX
This method is simple and if you would like to have a service for every single piece of data you need to pass, rather than a service for multiple pieces, this is the preferable choice. In difference to the JSON AJAX method, you will not be able to expand here and if needed, you'll naturally have to create a new service for passing new data.
Javascript AJAX
Altough it is possible, tis method is rather unadivsable, as you can not maintain your application in a reasonable way, as your templating is client-side. See what Peter-Paul Koch says here:
Although templating is the correct solution, doing it in the browser is fundamentally wrong. The cost of application maintenance should not be offloaded onto all their users’s browsers (we’re talking millions of hits per month here) — especially not the mobile ones. This job belongs on the server.
Further reading : Why client-side templating is wrong.
First approach looks good for me, but generally it's a little bit ugly to transfer raw HTML via AJAX, if you have to transfer raw HTML it's better to use techniques called PJAX, see jquery-pjax plugin for more information of how to use and customize it.
From my point of view best approach would start using jquery-template to avoid transferring HTML over AJAX and start transfer only object witch would be rendered to template on frontend.Call doit method within handling success is ok until it use data provided in response.
I would rather go with a variation of first approach. But, it depends on the kind of generated HTML that you are currently returning from the server-side.
If it is a simple element, then you could just return a JSON object from server with one of the properties identifying the element.
For example, the response from the web-service would be like:
{'elem': 'b', 'text': 'bold', 'value': '42'}
And you consume that in the AJAX call like this:
$.ajax({
datatype: "json",
...
success: function(response) {
// create the required element client-side
var elem = document.createElement(response.elem);
// use other properties of the response object
elem.textContent = response.text + doit(response.value);
// add the element to your div
$('#mydiv-1')[0].appendChild(elem);
}
});
Where doit is the Javascript function that is already part of your client-side code-base and you just use the arguments returned by the web-service.
Alternatively, if your generated HTML is a complex fragment, then you need to identify common patterns and use client-side templates to transform the returned data into presentation.
For example, your client-side template may look like this:
<script type='text/template' id='tmpl'>
<div><h3></h3><p></p><h5></h5></div>
</script>
Your web-service returns something like this:
{'title': 'title', 'text': 'paragraph', 'value': '42'}
And you consume that in the AJAX call like this:
$.ajax({
datatype: "json",
...
success: function(response) {
// clone the client-side template
var template = $('#tmpl').html(), $elem = $(template);
// append to your div
$('#mydiv-2').append($elem);
// populate the cloned template with returned object properties
$elem.find('h3').text(response.title);
$elem.find('p').text(response.text);
$elem.find('h5').text(doit(response.value));
}
});
This way you avoid returning generated HTML from your server and manage the presentation details at the client-side only. Your web-service needs not to know the presentational aspects and deals only with raw data (consuming or spewing). The client-side code gets data from the web-service and deals with using and/or presenting that data as part of the client-side app.
Demo for both the variations: https://jsfiddle.net/abhitalks/wuhnuv99/
Bottom-line: Don't transfer code. Transfer data. Code should then use that data.
I am having a hard time deciding on an appropriate way to Perform some server side functionality and then redirecting to the same View in my ASP.Net MVC project.
I am trying to call an Action after the selected index changed client side event of my combobox.
One way I can think of is to change the window.location to the url of my Action and pass the data i need via the query string like this
function SelectedIndexChanged(s,e)
{
window.location.href = "/MyController/MyAction?" + s.GetValue();
}
I also see lots of people saying you should use jquery ajax for this
function SelectedIndexChanged(s,e)
{
$.ajax({
url: 'MyController/MyAction',
data: { value: s.GetValue() },
success: function(){
alert('Added');
}
});
}
My Action looks something like this where i set some cookie values using the value and Set View bags values depending on the selected index.
public ActionResult SelectedIndexChanged(string value)
{
//Do some processing
//Set cookie values
SetViewBags(value);
return Redirect(Request.UrlReferrer.ToString());
}
Is there a better approach to accomplish my task, I am leaning more towards changing the location.href as it is simpler, but i'm not sure if this is good practice?
EDIT
To Clarify this Combobox is a Devexpress MVC extension so I will have to handle the "SelectedIndexChanged" client side event.
This Combobox is also on my layout page so it appears on every view in my project. So when it is changed i will need to to call the same Action no matter what page it is on
As you've indicated that your form is in your layout (not a view), I recommend you look at using a view partial. Fortunately, MVC has already provided an example with their view partial (can't remember the name) that has the login and logout buttons. If a user clicks logout, some javascript is fired and the form is submitted. This will redirect the user; however, you could also send the original address (referrer) as a parameter to your server method and then redirect to that page afterward.
You could always use an Html.Action
function SelectedIndexChanged(s,e)
{
#Html.Action("ActionName", "ControllerName", {optional route values})
}
Scenario:
I have written an MVC wizard that automatically uses ajax if javascript is enabled in the browser. Each step of the wizard is a PartialView (I'm using ASP.NET MVC 3).
All works fine.
The problem is refreshing the page if, for example, the user's status changes as a result of how she fills in the wizard. EG, if the wizard logs the user in, or registers them. As the wizard 'moves' from step to step by getting Partial Views via AJAX, the page doesn't get refreshed to reflect the change in the user's status (eg, an anonymous user is now registered).
What I want to do:
Essentially, when I need a full page refresh, I need to AUTOMATICALLY run the following on the client AFTER delivering the Partial View corresponding to the current step of the wizard via AJAX:
location.reload();
The Problem:
As the DOM has been modified via AJAX, I don't know how to make my javascript (location.reload();) run WITHOUT user intervention (eg, clicking a button).
Any suggestions? I have been off work for a while and am struggling to get back up to speed.
For now, I have solved my problem using the code in the following article:
Redirecting after AJAX call, when using ASP.NET MVC
I like the approach discussed in the article because it results in reusable code, in a very MVC way - I already have a base controller (AjaxController.cs) where I encapsulate all my AJAX aware code and this is a nice addition to it.
However, there are two issues with this approach:
I have to redirect away from my wizard, so it only works for the final step of the wizard. If the user's status changes half way through the wizard, I am still jiggered.
I would still like to know how to refresh my page after an AJAX call, rather than just redirecting like this.
So if anyone has the answer, I will gladly give them the biscuit.
I am not quite sure how your ajax calls are structured, but if you are using the MVC Ajax helper you can just call location.reload(); in the OnComplete method, like so:
#using (Ajax.BeginForm(new AjaxOptions{OnComplete = "javascriptfunction"}))
{
//Data and submit button
}
<script>
function javascriptfunction(){
location.reload();
}
</script>
// C# code
public ActionResult Foo(Bar bar)
{
// code here
return Json(new
{
Success = true,
Value = this.RenderPartialViewToString("PartialViewName", bar),
Callback = "window.location.href = 'http://yourdomainurl.com/';"
});
}
// jQuery Ajax
$.ajax({
type: "POST",
url: "/urlWhereToPost",
data: ("form#id").serialize(),
dataType: 'json',
async: false,
beforeSend: function() {
// some instruction
},
error: function(e) {
alert(e.responseText);
},
success: function(data) {
if (data.Success) {
if (data.Callback != null) {
if (data.Callback.length > 0) {
jQuery.globalEval(data.Callback);
}
}
}
else {
// do something
}
}
});
I have built a calendar in php. It currently can be controlled by GET values from the URL. Now I want the calendar to be managed and displayed using AJAX instead. So that the page not need to be reloaded.
How do I do this best with AJAX? More specifically, I wonder how I do with all GET values? There are quite a few. The only solution I find out is that each link in the calendar must have an onclick-statement to a great many attributes (the GET attributes)? Feels like the wrong way.
Please help me.
Edit: How should this code be changed to work out?
$('a.cal_update').bind("click", function ()
{
event.preventDefault();
update_url = $(this).attr("href");
$.ajax({
type : "GET"
, dataType : 'json'
, url : update_url
, async : false
, success : function(data)
{
$('#calendar').html(data.html);
}
});
return false;
});
Keep the existing links and forms, build on things that work
You have existing views of the data. Keep the same data but add additional views that provide it in a clean data format (such as JSON) instead of a document format (like HTML). Add a query string parameter or HTTP header that you use to decide which view to return.
Use a library (such as YUI 3, jQuery, etc) to bind event handlers to your existing links and forms to override the normal activation functionality and replace it with an Ajax call to the alternative view.
Use pushState to keep your URLs bookmarkable.
You can return a JSON string from the server and handle it with Ajax on the client side.
I have an asp.net mvc 3 application with some Action Method that handles GET requests and returns a page. Code looks like this:
[HttpGet]
public ActionResult Print(IEnumerable<string> arrayOfIds)
{
.......................
return View(someModel);
}
Also there is JavaScript code, that calls this action:
window.open('#Url.Action("Print","Appointments")' + urlArray, "Print", "width=620,height=410,scrollbars=yes");
Where urlArray can be really big. How can I pass this data to the Action Method without using URL string (maybe using content of HTTP Request)? I need it because URL is so big that browsers can't work with it.
UPD: May be my explanation wasn't really clear... I solved my problem. This is JavaScript code:
$.ajax({
url: '#Url.Action("Print","Appointments")',
type: "POST",
data: { listOfIds : listOfIds },
dataType: "text",
traditional: true,
success: function (data) {
printWindow = window.open('', 'Print');
printWindow.document.write(data);
}
});
Also I changed attribute of Action Method from HttpGet to HttpPost.
I don't think your question has much to do with JavaScript. The URL limitation is a feature of HTTP GET. You need to use HTTP POST, which you can't do with window.open().
However, you can do something like this...
window.open('about:blank', 'Print', 'width=620,height=410,scrollbars=yes');
document.myForm.target='Print';
document.myForm.urlArray=urlArray;
document.myForm.submit();
This opens a new window and posts an existing HTML form (method="post") to the new window. The example above assumes a hidden field with the name "urlArray", but you just need to supply whatever your Action Method expects.
You can tidy this up quite a bit if you have an existing form on the page already that you're using to capture the urlArray, you'll just need to target the form at a new window that is created by your form's onsubmit event handler.
You'll be better off posting a form to the current page (and thus transfer everything to the server side through POST) and then use RedirectToAction and pass your data at the server side.
It's a better way to do it. You can post the form using Javascript. So rather than window.open you'll be using form.submit()
EDIT:
Add target="_blank" to your form tag to open the results in a new window.