Can I call javascript function from MVC controller action (not from view page) and get return value? How?
I need to make request to server from code (.cs) using javascript like here (but this is aspx page)
function getInitData() {
var code; code = 'return {' ;
code += 'me: API.getProfiles({uids: API.getVariable({key: 1280}), fields: "photo"})[0]';
code += '};'
VK.Api.call('execute', { 'code': code }, onGetInitData);
}
For those that just used a standard form submit (non-AJAX), there's another way to fire some Javascript/JQuery code upon completion of your action.
First, create a string property on your Model.
public class MyModel
{
public string JavascriptToRun { get; set;}
}
Now, bind to your new model property in the Javascript of your view:
<script type="text/javascript">
#Model.JavascriptToRun
</script>
Now, also in your view, create a Javascript function that does whatever you need to do:
<script type="text/javascript">
#Model.JavascriptToRun
function ShowErrorPopup() {
alert('Sorry, we could not process your order.');
}
</script>
Finally, in your controller action, you need to call this new Javascript function:
[HttpPost]
public ActionResult PurchaseCart(MyModel model)
{
// Do something useful
...
if (success == false)
{
model.JavascriptToRun= "ShowErrorPopup()";
return View(model);
}
else
return RedirectToAction("Success");
}
You can call a controller action from a JavaScript function but not vice-versa. How would the server know which client to target? The server simply responds to requests.
An example of calling a controller action from JavaScript (using the jQuery JavaScript library) in the response sent to the client.
$.ajax({
type: "POST",
url: "/Controller/Action", // the URL of the controller action method
data: null, // optional data
success: function(result) {
// do something with result
},
error : function(req, status, error) {
// do something with error
}
});
Yes, it is definitely possible using Javascript Result:
return JavaScript("Callback()");
Javascript should be referenced by your view:
function Callback(){
// do something where you can call an action method in controller to pass some data via AJAX() request
}
It is late answer but can be useful for others.
In view use ViewBag as following:
#Html.Raw("<script>" + ViewBag.DynamicScripts + "</script>")
Then from controller set this ViewBag as follows:
ViewBag.DynamicScripts = "javascriptFun()";
This will execute JavaScript function.
But this function would not execute if it is ajax call.
To call JavaScript function from ajax call back, return two values from controller and write success function in ajax callback as following:
$.ajax({
type: "POST",
url: "/Controller/Action", // the URL of the controller action method
data: null, // optional data
success: function(result) {
// do something with result
},
success: function(result, para) {
if(para == 'something'){
//run JavaScript function
}
},
error : function(req, status, error) {
// do something with error
}
});
from controller you can return two values as following:
return Json(new { json = jr.Data, value2 = "value2" });
There are ways you can mimic this by having your controller return a piece of data, which your view can then translate into a JavaScript call.
We do something like this to allow people to use RESTful URLs to share their jquery-rendered workspace view.
In our case we pass a list of components which need to be rendered and use Razor to translate these back into jquery calls.
If I understand correctly the question, you want to have a JavaScript code in your Controller. (Your question is clear enough, but the voted and accepted answers are throwing some doubt)
So: you can do this by using the .NET's System.Windows.Forms.WebBrowser control to execute javascript code, and everything that a browser can do. It requires reference to System.Windows.Forms though, and the interaction is somewhat "old school". E.g:
void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
HtmlElement search = webBrowser1.Document.GetElementById("searchInput");
if(search != null)
{
search.SetAttribute("value", "Superman");
foreach(HtmlElement ele in search.Parent.Children)
{
if (ele.TagName.ToLower() == "input" && ele.Name.ToLower() == "go")
{
ele.InvokeMember("click");
break;
}
}
}
}
So probably nowadays, that would not be the easiest solution.
The other option is to use Javascript .NET or jint to run javasctipt, or another solution, based on the specific case.
Some related questions on this topic or possible duplicates:
Embedding JavaScript engine into .NET
Load a DOM and Execute javascript, server side, with .Net
Hope this helps.
The usual/standard way in MVC is that you should put/call your all display, UI, CSS and Javascript in View, however there is no rule to it, you can call it in the Controller as well if you manage to do so (something i don't see the possibility of).
Since your controller actions execute on the server, and JavaScript (usually) executes on the client (browser), this doesn't make sense. If you need some action to happen by default once the page is loaded into the browser, you can use JavaScript's document.OnLoad event handler.
<script>
$(document).ready(function () {
var msg = '#ViewBag.ErrorMessage'
if (msg.length > 0)
OnFailure('Register', msg);
});
function OnSuccess(header,Message) {
$("#Message_Header").text(header);
$("#Message_Text").text(Message);
$('#MessageDialog').modal('show');
}
function OnFailure(header,error)
{
$("#Message_Header").text(header);
$("#Message_Text").text(error);
$('#MessageDialog').modal('show');
}
</script>
Related
In my DotNet Core application, I have a button set up with the some javascript placed in for my OnClick event. It looks like this:
<div>
#(Html.DevExtreme().Button()
.Text("Press me")
.Type(ButtonType.Normal)
.Width(90)
.OnClick("notify")
)
</div>
<script>
function notify() {
console.log("pressed");
// ModifiedDuration.AdjustmentScreen_Netting.Csharp.RunBatch();
// var a = '<%=RunBatch()%>';
}
</script>
The commented out lines are what I've tried to call my target method but neither have worked. The underlying method I want to call is this:
public void RunBatch()
{
Console.WriteLine("Re-running batch");
TestOutput print= new TestOutput ();
print.TestMethod();
}
Then, what TestMethod does:
public void ProcessAdjustedBatch()
{
Console.WriteLine("I have been called from the datagrid!!!!");
}
So after I press the button, I would expect to see the following log messages:
Pressed
re-running batch
I have been called from the datagrid!!!!
But all that I see is Pressed in my dev log. How can I achieve my intended output?
Console.WriteLine() will never shown in client's browser because it runs server-side and opened in server's console window. It is necessary to use Debug.WriteLine() if you want to see debug messages in immediate output window.
Also note that var a = '<%=RunBatch()%>' only executes inside ASPX pages, it cannot be executed in Razor which uses #{ ... } for code segment, and both debug methods are server-side methods.
If you want to show server-side debug message in browser's console with console.log(), you need to create a controller action that executes both methods which have string return type and then use AJAX inside notify() function which outputs the result in success part.
Here is a simple example:
Controller Action
public IActionResult GetMessages()
{
var messages = new StringBuilder();
messages.Append(RunBatch());
messages.Append("\n"); // use newline to separate messages from different methods
messages.Append(ProcessAdjustedBatch());
return Json(messages.ToString(), JsonRequestBehavior.AllowGet);
}
Debug Methods
public static string RunBatch()
{
string batch = "Re-running batch";
Debug.WriteLine(batch);
TestOutput print = new TestOutput();
print.TestMethod();
return batch;
}
public static string ProcessAdjustedBatch()
{
return "I have been called from the datagrid!!!!";
}
View (script tag)
<script>
function notify() {
console.log("pressed");
$.ajax({
type: 'GET',
url: '#Url.Action("GetMessages", "ControllerName")',
dataType: 'json',
success: function (result) {
console.log(result);
}
});
}
</script>
Now the console output should be like this:
pressed
Re-running batch
I have been called from the datagrid!!!!
Live example: .NET Fiddle
Related issues:
Where does Console.WriteLine go in ASP.NET?
Asp.net mvc Console.WriteLine to browser
How to use Console.WriteLine in ASP.Net MVC 3
in JavaScript
<script>
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", '#Url.Action("****", "****")',true);
xmlHttpRequest.onloadend = function() {
#{
var res = (UserResponseMvc) TempData["UserResponse"];
}
#Html.ShowAlert(res?.Message)
}
xmlHttpRequest.send();
</script>
in Controller
public ActionResult Upload() {
//code
TempData["UserResponse"] = new UserResponseMvc
{
Success = true,
Message = "Upload Success"
};
return View();
}
In this piece, the code does not know the res variable.
How can I use the res variable here?
I write in Asp.net Mvc code.
Pls help me.
You can like this:
View
<input type="button" value="ClickToSend" onclick="sendToAction()" />
<script>
function sendToAction() {
var res = ["Upload1", "Upload2", "Upload3"]; // Sample
jQuery.ajax({
type: "POST",
url: "#Url.Action("Upload")", // Upload is your action in controller
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(res),
success: function (data) { alert(data); },
failure: function (errMsg) {
alert(errMsg);
}
});
}
</script>
Action
[HttpPost]
public ActionResult Upload(List<String> res)
{
return View();
}
I think that can not happen
ShowAlert if only the function displays the message, then it should be a function of javascript.
You can't. and the reason is that they do not "live" in the same time.
The Razor variables are "Server side variables" and they don't exist
anymore after the page was sent to the "Client side".
When the server get a request for a view, it creates the view with
only HTML, CSS and Javascript code. No C# code is left, it's all get
"translated" to the client side languages.
The Javascript code DO exist when the view is still on the server, but
it's meaningless and will be executed by the browser only (Client side
again).
This is why you can use Razor variables to change the HTML and
Javascript but not vice versa. Try to look at your page source code
(CTRL+U in most browsers), there will be no sign of C# code there.
In short:
The server get a request.
The server creates "takes" the view, compute and translate all the C# code that was embedded in the view, to CSS,Javascript, and HTML.
The server returns the client side version of the view to the browser as a response to the request.
the browser renders the page and executes all the Javascripts
Refer to How to pass a value to razor variable from javascript variable?
In your case, I have a some documents for you refer.
jQuery Ajax File Upload
File upload using MVC 4 with Ajax
So I'm getting a bit stumped by this one. I've got multiple pages making lots of successful Ajax calls to my C# controllers on the back end with a variety of data, but now I'm trying to build a simple little content management functionality, and hence update the HTML in a database with new HTML from a JS editor.
Long story short, I've taken out all the heavy Database code and narrowed it down to the fact that either my controller won't accept anything with html tags, or my ajax code is having trouble sending it.
The Ajax function is:
$.ajax({
type: "POST",
url: '#Url.Action("UpdateContent", "Admin")',
data: {
elementId: elementId,
newContent: newContent
},
dataType: "json",
success: function (data) {
if (data.result == 'true') {
infoMessage('Content Updated!', 'success');
} else {
infoMessage('Error: ' + data.result + '. Nothing has been updated!', 'error');
}
},
error: function () {
alert('There was a problem contacting the server.');
}
});
And on my Controller side, I've taken away all the code to just leave some debugging write lines.
[HttpPost]
public ActionResult UpdateContent(string elementId, string newContent)
{
System.Diagnostics.Debug.WriteLine("!" + elementId);
System.Diagnostics.Debug.WriteLine("!" + newContent);
string _result = "true";
return Json(new { result = _result });
}
Now the interesting thing is that when I have newContent in the data paramater in the Ajax request set to anything like <p>hello</p> those writelines don't even get called and the whole ajax call fails. Yet when I just use a normal string e.g. hello it works fine. I've further narrowed it down to just the opening html bracket, so even <p would fail.
With this in mind, what is happening here? And secondly, what is the correct way to send html back to the controller via Ajax so this doesn't happen?
ASP.NET has request validation enabled by default to help protect against XSS. You can disable this by adding the ValidateInput attribute to your action:
[HttpPost]
[ValidateInput(false)]
public ActionResult UpdateContent(string elementId, string newContent)
{
System.Diagnostics.Debug.WriteLine("!" + elementId);
System.Diagnostics.Debug.WriteLine("!" + newContent);
string _result = "true";
return Json(new { result = _result });
}
You'll also need to add the following to your web.config:
<httpRuntime requestValidationMode="2.0" />
A newer (and better) alternative is to use the AllowHtml attribute which you would apply to a property on your model. This is preferred because you're only allowing this prop to bypass validation instead of the entire request.
class MyModel
{
[AllowHtml]
public string MyHtml { get; set; }
}
I was looking up some ways to redirect from an ajax request and came across a solution:
return JavaScript("window.location = 'http://www.google.co.uk'");
I was told that this might get wrapped in an eval upon its return, which can change how the code is compiled and effect efficiency.
eval("window.location = 'http://www.google.co.uk'"); //actually gets executed
I was told to change it to just return the redirect url.
Two questions about this:
1) Would executing an eval, in a 'success' through an ajax request, effect the compilation of other javascript?
2) What happens when I return from my post with a JavaScript ActionResult? Does it eventually run inside an eval (implicitly)?
// In MVC Controller
[HttpPost]
public ActionResult MyAction()
{
return JsonResult("window.location = 'url'");
}
// In javascript
$.ajax({
type: 'POST',
url: '/MyAction'
});
JavaScriptResult simply returns JavaScript to the client, so you can, for instance, access it from a <script> element:
<script src="/MyCoolController/GiveMeScript?param5=7"></script>
How that JavaScript gets executed is up to you.
I don't really see why the performance of eval() would be a concern if your objective is to redirect the page, but this sounds like a pretty questionable approach to (especially if it involves eval()).
Why not just return a JsonResult that indicates a redirect using some pre-decided convention, and then have your script act accordingly:
// in controller
return JsonResult(new { redirectTo = "http://www.google.co.uk" });
// in script
$.ajax({
type: 'POST',
url: '...',
success: function (result) {
if (result.redirectTo) {
window.location = result.redirectTo;
}
// handle result if not redirecting ...
}
});
I have a mvc application. I am trying to call a javascript function (say Create) in the controller action code...my idea here is that when a user hits http://localhost/somecontroller/someaction/id.. the controller should run the Create function..in this function i am using xhrget to get the information from a webservice and it writes to the view..now my question is how do i call the Create function in the controller
here is the Create function
Create: function (obj)
{
var xhrGet1 = dXhr.get({
url: "http://localhost/SomeService/parameter?id=" + obj.id,
handleAs: "json",
headers: { 'accept': 'application/json' }
});
---
---
---
}
Here is how i started the controller and not able to move forward with this...Any ideas?
Function somecontroller (id As string) As ...
Thank you.
If you're trying to directly call the Create function that presumably lives in your client-side javascript code using somecontroller, you'll want to do something like this in your ActionResult method that intercepts the initial request that lives in somecontroller:
ViewBag.Id = id
And then in your .cshtml view you would have to add this function on your page load (either $(document).ready() { ... } with jQuery or simply window.onload = function() { ... }:
someObj.Create({id: #ViewBag.Id});
BUT there are better ways to do this. One simple solution may be to simply call the http://localhost/SomeService/ in your controller and pass the result as a strongly-typed model to your view?