Is it possible to run jQuery from a MVC C# controller?
if (ModelState.IsValid){
//lots of C# asp.net code here
jqueryFunctionName();
}
It's important that there is a check somehow before the jQuery runs
Perhaps i can do it straight from jQuery itself, but i'm not sure how to check it?
The idea is Form -> Submit -> SOMETHING checks if valid -> if yes then wait graphic -> 2 seconds pauze -> redirect to "thanks.cshtml"
In your controller's action:
var vm = new YourViewModelTypeWithPropertyIsValid();
vm.IsValid = ModelState.IsValid;
return View(vm);
In your view:
#model YourViewModelTypeWithPropertyIsValid
<script type="text/javascript">
var isModelValid = #Model.IsValid ? 'true' : 'false';
$( document ).ready(function() {
// Any JS code here
// ...
if (isModelValid) {
setTimeout(
function () {
location.assign('/redirect_path_after_2s_delay');
},
2000);
);
}
});
<script>
I prefer typed views.
If you use untyped views, use the code below.
In your controller's action:
ViewData["IsModelValid"] = ModelState.IsValid ? "true" : "false";
return View();
In your view:
<script type="text/javascript">
var isModelValid = #ViewData["IsModelValid"];
$( document ).ready(function() {
// Any JS code here
// ...
if (isModelValid) {
// See the code above.
}
});
<script>
If the code runs in the view then you can try something like this.
is a special asp tag.
If the should indeed run in controller, than it is not possible to run JS code there.
if (ModelState.IsValid){
//lots of C# asp.net code here
<text>
<script>
jqueryFunctionName();
</script>
</text>
}
Related
This is the way I was sending my model to an angular controller scope.
c# Controller:
public class AreaMenuController : RootController
{
// GET: Menu
public PartialViewResult Index()
{
var mod = Modules.Instance.ModuleList.FirstOrDefault(m => m.Prefix.Equals(base.GetArea(), StringComparison.CurrentCultureIgnoreCase));
return PartialView("_AreaMenu", mod.ModuleMenus);
}
}
View cshtml:
#using Nuclei.Models
#model IEnumerable<Nuclei.Models.Menu>
<script type="text/javascript">
#{ var serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); }
window.areaMenus = #Html.Raw(serializer.Serialize(Model));
</script>
<script type="text/javascript" src="#Url.Content("~/Scripts/AngularControllers/_AreaMenuController.js")"></script>
<div ng-controller="AreaMenuController as vm" ng-init="vm.initializeController()">
<div id="accordion" ng-class="accordian-menu" style="visibility: visible;">
<ul>
<li ng-repeat="menu in vm.areaMenus">
...
</li>
</ul>
</div>
</div>
Angular Js file:
var NucleiApp = angular.module('NucleiApp');
NucleiApp.controller('AreaMenuController', ['$scope', '$http', '$location', function ($scope, $http, $location) {
"use strict";
var vm = this;
vm.initializeController = function () {
vm.areaMenus = window.areaMenus;
}
}]);
Question 1: Is there a smoother way to send your c# model through to angular other than through global window object?
You can use an $http get from angular, however because this is processed client-side there is always a bit of lag before it gets displayed, because it needs to call the c# controller and get the data. So I'm reserving $http get for updates only.
The other other way I was thinking was to send the view a Json object straight off:
c# controller:
public class AreaMenusController : RootController
{
// GET: Menu
public PartialViewResult Index()
{
return PartialView("_AreaMenu", GetAreaMenus());
}
public JsonResult GetAreaMenus()
{
var mod = Modules.Instance.ModuleList.FirstOrDefault(m => m.Prefix.Equals(base.GetArea(), StringComparison.CurrentCultureIgnoreCase));
return Json(new { areaMenus = mod.ModuleMenus }, JsonRequestBehavior.AllowGet);
}
}
View cshtml:
#using System.Web.Mvc
#model JsonResult
<script type="text/javascript">
window.areaMenus = #Model;
</script>
Question 2: I'm not really sure how to initialize the #model at this point and send it through to the angular file and again, if there is a better option than javascripts global window object... open to suggestions!
We currently do this to bootstrap a set of data that is later updated by a call into a WebAPI.
The reason we do this is we have found cases where the data, when bootstrapped via an API call, was coming back too slowly, which gave a bad experience to our users.
In our razor view:
<html>
<head>
<script>
window.areaMenus = '#Html.Raw(Model.SerializedJsonString)';
</script>
</head>
</html>
Then when our angular app is Run(), we deserialize the data, and use it from there:
var app = angular.module('myApp', ["stuff"])
.run(["menuService", (menuService) => {
// deserialize the json string into my object
var areaMenus = angular.fromJson(window.areaMenus);
// do something with it
menuService.Load(areaMenus);
}]);
This'll get the data available to angular immediately without having to wait for a $http request to complete, which should address your issue.
I'm trying to call a confirm, then an alert function from an MVC action link and I'm stuck. The code is as follows:
My view has the following actionlink:
#Html.ActionLink("JQuery Testing", "BuildProject", Model, new { onclick = " return ConfirmProjectSubmit()" })
which calls the controller to save a project to the database. I'm trying to throw a confirm statement onClick. Once that action is performed, the following action is called:
return RedirectToAction("ProjectDetails", "Project", new RouteValueDictionary(new { id = currentProject.Id, msg = message }));
to alert the user that the project was actually created.
and then at the bottom of my view:
#section scripts {
<script type="text/javascript">
function ConfirmWorkflowSubmit() {
$.confirm({
title: 'Confirm!',
content: 'Simple confirm!',
buttons: {
confirm: function () {
},
cancel: function () {
}
}
});
return false;
};
</script>
#if (ViewBag.message != null)
{
<script type="text/javascript">
$(document).ready(function () {
$.alert({
title: 'Workflow successfully created',
content: '#ViewBag.message',
type: 'green',
});
});
</script>
}
}
both of the actions are firing, but incorrectly. I'm newer to MVC and moreso to Jquery. Basically I need to figure out how to not have it submit if the user doesn't confirm, and then make sure the message only pops on the way back. I think I just need help ordering what I have properly.
Thanks in advance.
EDIT. Okay, so I see part of the problem. It's not the $confirm function that's actually submitting the form, it's the button action clicked once the dialog is open. I'm really stuck here, and this has to be easier than I'm making it. Help!
I'm not saying you can't do it the way you have, but this is normally how I set up my bindings:
$(document).ready(function ()
{
// add the e here -- it is the event which initiated the binding
$(".buildButton").on("click", function (e)
{
if (ConfirmProjectSubmit())
{
alert('confirm');
}
else
{
// e.preventDefault() cancels the click action
e.preventDefault();
alert('cancel');
}
});
});
function ConfirmProjectSubmit()
{
// some confirm logic
// return true for confirmed, false for cancelled
return false;
}
Remove the onclick in your action. There is no need to have a jQuery binding and an onClick.
This is sort of an outline, you can add your logic in various places to finish it out.
I am implementing a simple JQuery autocomplete with few entries so I don't need to use a web method. The code is like this:
$( function() {
var availableTags = [
"ActionScript",
"AppleScript"
];
$( "#tags" ).autocomplete({
source: availableTags
});
} );
The entries availableTags are unique to the user so they need to come from the server. How should I get the entries from the server side to the JavaScript in ASP.NET Core?
This assumes you have some service IUserTagService like this, registered through dependency injection:
public interface IUserTagService
{
IList<string> GetUserTags();
}
Since you don’t want (or need) an AJAX call here to load the tags after the page has been rendered, we’re just going to render the tags directly into the output. For that, we basically convert the returned list from the GetUserTags method into JSON and put this into a script tag. So the end result will look mostly like your static example.
So in the .cshtml view, we first inject our service. We can use the #inject directive at the beginning of the file for this:
#inject IUserTagService userTagService;
Then, we simply open a script tag and write the output into a variable:
<script>
$(function() {
var availableTags = #Json.Serialize(userTagService.GetUserTags());
$("#tags").autocomplete({
source: availableTags
});
});
</script>
This uses the Json.Serialize which is a utility function that is available in views to serialize the list into JSON.
You can make an ajax call to your server action method which returns the list as JSON array.
$(function () {
$.getJSON("#Url.Action("GetItems")", function (availableTags) {
$( "#tags" ).autocomplete({
source: availableTags
});
});
})
Assuming your GetItems action method returns the list of items as json array
public JsonResult GetItems()
{
var list = new List<string>() {"ActionScript","AppleScript"};
return new JsonResult(list);
}
Another option is to load the data (list of strings to your main views GET action method and in the razor view, convert that to a JS Array
So in your GET action,
var list = new List<string>() {"ActionScript","AppleScript"};
ViewBag.Items = list;
return View();
and in the razor view,
#section Scripts
{
<script>
$(function() {
var availableTags = #Html.Raw(Newtonsoft.Json.JsonConvert
.SerializeObject(ViewBag.Items));
$( "#tags" ).autocomplete({
source: availableTags
});
});
</script>
}
Dependency injection is possible in asp.net core views now. poke's answer above uses that. You may consider doing that instead of the ViewBag solution above.
I have a function in jQuery to disable input based on user roles. But I don't know how to get the current ASP.Net MVC user role in jQuery.
Below is the code but it is not working:
$(function () {
if (Roles.IsUserInRole('user'))
{
$("#GenericName").prop("disabled", true);
$("#TradeName").prop("disabled", true);
$("#Form").prop("disabled", true);
$("#Strength").prop("disabled", true);
$("#IsBrandSubstitutionAllowed").prop("disabled", true);
$("#Route").prop("disabled", true);
$("#Dosages").prop("disabled", true);
$("#Unit").prop("disabled", true);
$("#PackTypes").prop("disabled", true);
$("#GeneratedDirection").prop("disabled", true);
$("#UserDirection").prop("disabled", true);
$("#StartDate").prop("disabled", true);
$("#EndDate").prop("disabled", true);
}
});
The problem: You are mixing Javascript and Razor Views.
What you have:
if (Roles.IsUserInRole('user'))
{
should actually be written as:
var userRole = '#(Roles.IsUserInRole("user") ? "true" : "false")';
if(userRole) {
...
This code #(Roles.IsUserInRole('user') ? "true" : "false") will output true or false literal string (as it's not wrapped in single or double quotes, javascript will interpreter as a boolean value) and you can just use that new assign variable.
What I normally do, is in my _Layout.cshtml view, I add a simple Global Javascript that I can easily call through my application... for example and assuming that you have a CurrentUser object on that View (through ViewData or Model):
<html>
<head>
<title>Your App</title>
<styles ... >
<script>
var AppGlobal = {
"user" = {
"name" : "#(CurrentUser.Name)",
"id" : "#(CurrentUser.Guid.ToString())",
"role" : "#(CurrentUser.Role.Name)"
},
...
};
</script>
</head>
<body>
#RenderBody()
</body>
</html>
Then it's easier, in your case to do:
if(AppGlobal.user.role === 'user') {
...
I would suggest to do an AJAX call in order to get user role.
After ajax calling, based on response received then you disable/enable inputs.
like:
$.ajax({
url: 'Controller1/Action1',
dataType: 'json',
data: {},
type: 'post',
success: function(data){
if(data.user === 'user') {
// disable inputs here !
}
}
});
and your controller called Controller1Controller:
[HttpPost]
public JsonResult Action1(){
return Json(new {
user = // put current user role here !
});
}
Also, I'd suggest to use ValidateAntiForgeryToken in order to avoid CSRF attack but seems to be fine since there are no form.
var userRole = '#(User.IsInRole("user") ? "true" : "false")';
if(userRole) {
...
In my case I had to use the if condition like this
If(userRole=="true"){
...
}
then the code hit the condition else it was skipping it.
You can only use C# code, like Roles.IsUserInRole('user') if you're writing JavaScript code in Razor view.
As a workaround, you can create an action to tell you the user's permission or maybe role, which you will need to send a request to, every time permissions are needed. You can also keep a copy of the status returned to save subsequent requests. According to your project, you can use it with more sophistication and make separate your authorization logic.
Using MVC 5.2.2, this worked for me
var userRoleAdmin = '#(Request.IsAuthenticated && User.IsInRole("Admin")) ? "true" : "false")';
if(userRoleAdmin) {
...
I want to redirect from one page to another page in ASP.NET MVC 3.0 using JavaScript/jQuery/Ajax. On button click event I have written JavaScript code like below.
function foo(id)
{
$.post('/Branch/Details/' + id);
}
My controller code is like this:
public ViewResult Details(Guid id)
{
Branch branch = db.Branches.Single(b => b.Id == id);
return View(branch);
}
When I click on a button it is calling the Details action inside BranchController, but it doesn't return to the Details view.
I didn't get any error or exception. It's showing status 200 OK in Firebug. What is wrong in my code and how can I redirect to the Details view page?
You are not subscribing to any success callback in your $.post AJAX call. Meaning that the request is executed, but you do nothing with the results. If you want to do something useful with the results, try:
$.post('/Branch/Details/' + id, function(result) {
// Do something with the result like for example inject it into
// some placeholder and update the DOM.
// This obviously assumes that your controller action returns
// a partial view otherwise you will break your markup
});
On the other hand if you want to redirect, you absolutely do not need AJAX. You use AJAX only when you want to stay on the same page and update only a portion of it.
So if you only wanted to redirect the browser:
function foo(id) {
window.location.href = '/Branch/Details/' + id;
}
As a side note:
You should never be hardcoding urls like this. You should always be using url helpers when dealing with urls in an ASP.NET MVC application. So:
function foo(id) {
var url = '#Url.Action("Details", "Branch", new { id = "__id__" })';
window.location.href = url.replace('__id__', id);
}
This could be done by using a hidden variable in the view and then using that variable to post from the JavaScript code.
Here is my code in the view
#Html.Hidden("RedirectTo", Url.Action("ActionName", "ControllerName"));
Now you can use this in the JavaScript file as:
var url = $("#RedirectTo").val();
location.href = url;
It worked like a charm fro me. I hope it helps you too.
You can use:
window.location.href = '/Branch/Details/' + id;
But your Ajax code is incomplete without success or error functions.
// in the HTML code I used some razor
#Html.Hidden("RedirectTo", Url.Action("Action", "Controller"));
// now down in the script I do this
<script type="text/javascript">
var url = $("#RedirectTo").val();
$(document).ready(function () {
$.ajax({
dataType: 'json',
type: 'POST',
url: '/Controller/Action',
success: function (result) {
if (result.UserFriendlyErrMsg === 'Some Message') {
// display a prompt
alert("Message: " + result.UserFriendlyErrMsg);
// redirect us to the new page
location.href = url;
}
$('#friendlyMsg').html(result.UserFriendlyErrMsg);
}
});
</script>
<script type="text/javascript">
function lnkLogout_Confirm()
{
var bResponse = confirm('Are you sure you want to exit?');
if (bResponse === true) {
////console.log("lnkLogout_Confirm clciked.");
var url = '#Url.Action("Login", "Login")';
window.location.href = url;
}
return bResponse;
}
</script>
check the code below this will be helpful for you:
<script type="text/javascript">
window.opener.location.href = '#Url.Action("Action", "EventstController")', window.close();
</script>