I tried show a alert box in mvc controller by if-else condition.But alert box does not display.Where is my mistake ?
Controller
public ActionResult Index()
{
int userId = Convert.ToInt32(Session["userId"].ToString());
if (WebMatrix.WebData.WebSecurity.IsAuthenticated)
{
if (userId == 90043)
{
return View();
}
else
{
TempData["Message"] = "You are not authorized.";
return RedirectToAction("Index", "Home");
}
}
else
{
return RedirectToAction("Index", "Home");
}
}
TempData["msg"] = "<script>alert('Change succesfully');</script>";
#Html.Raw(TempData["msg"])
Use this:
return JavaScript(alert("Hello this is an alert"));
or:
return Content("<script language='javascript' type='text/javascript'>alert('Thanks for Feedback!');</script>");
You cannot show an alert from a controller. There is one way communication from the client to the server.The server can therefore not tell the client to do anything. The client requests and the server gives a response.
You therefore need to use javascript when the response returns to show a messagebox of some sort.
OR
using jquery on the button that calls the controller action
<script>
$(document).ready(function(){
$("#submitButton").on("click",function()
{
alert('Your Message');
});
});
<script>
It is not possible to display alerts from the controller. Because MVC views and controllers are entirely separated from each other. You can only display information in the view only. So it is required to pass the information to be displayed from controller to view by using either ViewBag, ViewData or TempData. If you are trying to display the content stored in TempData["Message"], It is possible to perform in the view page by adding few javascript lines.
<script>
alert(#TempData["Message"]);
</script>
<a href="#Url.Action("DeleteBlog")" class="btn btn-sm btn-danger" onclick="return confirm ('Are you sure want to delete blog?');">
Response.Write(#"<script language='javascript'>alert('Message:
\n" + "Hi!" + " .');</script>");
I know this is not typical alert box, but I hope it may help someone.
There is this expansion that enables you to show notifications inside HTML page using bootstrap.
It is very easy to implement and it works fine. Here is a github page for the project including some demo images.
In Controller
TempData["err"] = "Something happenend";
In your view
var error = '#TempData["err"]';
if(error){
alert(error);
}
Related
I have a problem right now and I hope you can help me.
My problem is that I have a Controller in which I generate a file as byteArray (without saving it on hard disk), which I return to download.
These action takes up to 5-6 seconds until its generated. Now I would like to display a busy indicator for the user, but I don't know, how can I identify, when my controller is done!?
Here is my code:
This is the code to call my Controller action in my "View.cshtml":
<span class="fa fa-bar-chart"></span>
This my Controller code:
public ActionResult DownloadAnalysis()
{
var response = StartAnalysis();
if (response.AnalysisByteArray != null && response.AnalysisByteArray.Length > 0)
{
var cd = new System.Net.Mime.ContentDisposition
{
FileName = response.FileName,
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(response.AnalysisByteArray , "text/csv");
}
return null;
}
I thank you in advance for your help!
Best Regards
Instead of the anchor tag use a button and onclick event to call the controller.
your html should be like
<button title="Get analysis file" onclick="getFile()"><span class="fa fa-bar-chart"></span></button>
and in JavaScript use window.location to call the controller action
<script>
function getFile(){
//here you can add script to change cursor to progress of add some html element to show loading.
window.location.href = '/Analysis/DownloadAnalysis/';
}
</script>
Im developing a project with ASP.NET Core 2.2 MVC. Here is a view named MyView in which there is a link which calls MyAction action.
<div>
<a asp-controller="Home" asp-action="MyAction">my link</a>
</div>
And this is MyAction which does st.
public async Task<IActionResult>MyAction(argument1,argument2)
{
if(a condition)
{
it should redirect me to the view which *MyLink* is placed there.
}
else
{
return false;
}
}
I want to know how can I find the url of the view(page) which called MyAction and redirect to it.
This is project structure(I made it simple)
project structure
I found this. But I want to add NOTHING to the destination action. It doesn't work in .NET Core
How do I redirect to the previous action in ASP.NET MVC?
My solution
I did it. Here is how you can redirect to the view which called the action.
Mayak provided a good solution for it. I just added some extra information to make it secure. As he/she said,
first,you should assign Title to all Views.
And after that you should pass Path and QueryString Via asp-route-returnUrl.
#{
ViewData["Title"] = "MyView";
}
<div>
<a asp-controller="Home" asp-action="MyAction" asp-route-returnUrl="#string.Format("{0}{1}",Context.Request.Path, Context.Request.QueryString)" >my link</a>
</div>
Then in MyAction we pass the returnUrl as an argument
public async Task<IActionResult>MyAction(string returnUrl)
{
if(everything is alright)
{
return LocalRedirect(returnUrl);
}
else
{
return false;
}
}
There is something called open redirect attack
https://learn.microsoft.com/en-us/aspnet/core/security/preventing-open-redirects?view=aspnetcore-2.2
When your application receives data from a form. It's not secure and data can potentially be tampered with to redirect users to an external, malicious URL. So by using LocalRedirect you can prevent open redirect attacks.
You can use title or specific id for every page. After you assigned ViewData["Title"] in the view (or you can use specific id for everypage without assigning title)
#{
ViewData["Title"] = "MyView";
}
<div>
<a asp-controller="Home" asp-action="MyAction" asp-route-returnUrl="#ViewData["Title"]" >my link</a>
</div>
Then you can use it in action
public async Task<IActionResult>MyAction(string returnUrl)
{
return View(returnUrl)
return RedirectToAction(returnUrl,"YourAction")
}
If you are gonna do something different use switch case for the reminder string like (redirecttoaction or whatever you like)
switch (returnUrl)
{
case"MyView":
.....
break;
case "YourView":
.....
break;
default:
...
break;
}
I have an Action Method that sets a message to ViewBag and returns to the HomePage, like,
ViewBag.errormsg = "Some Temporary message";
return RedirectToAction("Index", "Dashboard");
As per this approach User won't be able to see the ViewBag.errormsg in that page, Because it redirects to Dashboard immediately, But I want to show That message for 1 to 2 second then after redirect to dashboard.
I have tried using Task.WaitAll(); method to delay the call for RedirectToAction like here,
ViewBag.errormsg = "Some Temporary message";
Task.WaitAll(Task.Delay(2000));
return RedirectToAction("Index", "Dashboard");
But it's fairly a silly work, that ViewBag won't show message until the return method is called, Is there any simple way to accomplish this ?
I think TempData is not suitable in my case because I don't want to show that ViewBag Message to HomePage, It should be shown in the current page.
You wont be able to do that on the server side, you'll have to use javascript.
You can use:
window.setTimeout(function(){
window.location.href='your URL';
}, 2000);
I figured out what process that you want to do:
Controller => Current view => Redirect => Dashboard view
First, include your message in current view:
ViewBag.errormsg = "Some Temporary message";
return View("CurrentView");
Set an HTML element to show that message and use JS timeout on current CSHTML view:
<script type="text/javascript">
function onMessageShow() {
var msg = "#ViewBag.errormsg";
// if the message exists, set redirection to dashboard page
if (msg != null || typeof msg !== "undefined") {
setTimeout('redirect', 5000); // 5 seconds for example
}
}
function redirect() {
window.location.href = "#Url.Content("Index", "Dashboard")";
// or use window.location.replace, depending what your need
}
</script>
<html>
<body onload="onMessageShow()">
<!-- simplified for brevity -->
<p>#ViewBag.errormsg</p>
<!-- simplified for brevity -->
</body>
</html>
Task.WaitAll with Task.Delay used together in server-side to delay execution of server-side process (including async processes), in your case there are client-side events which redirecting to index page after message appears.
CMIIW.
Imagine I have a Partial View with a list of users ( loop ) where each user is another partial view with details about one.
foreach (var user in Model.Users)
{
<a href="#" onclick="JavascriptFunction(user.Id);">Details<a>
}
When I click the above Details link for one of the list items a popup (JQuery modal dialog() ) pops up with details about that selected user. Or at least that's the goal. I need to get the selected user details to a new popup that opened.
So now I need to populate the model behind the partial view that the popup will contain with user details before .dialog('Open') triggers.
Question: What's the best way, from within a Javascript function ( onclick JavascriptFunction function in the example above) to call an ActionMethod and populate the Partial View model before the dialog is displayed ?
Right now I'm doing it the following way but for whatever reason I'm getting major delays in data being rendered on the page. I see blank div for good 5-10 seconds before .html() finally displays data:
On the main list page:
<div id="userPopup"></div>
Javascript that suppose to load Partial view with User details from an ActionMethod:
$.post('#Url.Action("Details","User")', { id: userId},
function (data) {
$("#userPopup").html(data);
});
Possibly there is a way to pre-load a partial view on the page and then just load my data into its Model without re-writing the entire PartialView ?
That would be the ideal scenario but I don't think there is a way to do it, is there ?
Thank you in advance ! Don't hesitate to ask questions if anything sounds confusing.
I dont think you should preload all the user details on the main page, what if you have 1000+ users and the visitor is not clikcking the details link ! I would do it in this way. Whenever user clicks on the link, make a call to an action method which returns the data.
So in your main view,
#foreach(var user in Model.Users)
{
#Html.ActionLink(user.Name, "Details", "User",
new { Id = user.ID, }, new { #class ="popupLink" })
}
<script type="text/javascript">
$(function(){
$(".popupLink").click(function (e) {
e.preventDefault();
var url = this.href;
var dialog = $("#dialog");
if ($("#dialog").length == 0) {
dialog = $('<div id="dialog" style="display:hidden"></div>').appendTo('body');
}
dialog.load(
url,
{}, // omit this param object to issue a GET request instead a POST request, otherwise you may provide post parameters within the object
function (responseText, textStatus, XMLHttpRequest) {
dialog.dialog({
close: function (event, ui) {
dialog.remove();
},
modal: true,
width: 460
});
}
);
});
});
</script>
In User controller, have an action method called "Details which accepts the Id as parameter and return the View of User details
public ActionResult Details(int id)
{
var usre=repositary.GetUser(id);
return View(user);
}
Have your HTML markup for details in the DetailsView.
This code use jQuery UI model dialog. So you need to include that.
I have a view that displays a list of comments. It does this via the DisplayTemplate. All I have to do is something like #Html.DisplayFor(x => x.BlogPost.PostComments) and all the comments render appropriately.
There is a form at the bottom of the page to add a new comment. This page utilizes progressive enhancement. So if javascript is disabled then the form submits like normal, adds the comment to the database, then redirects to the action that renders the blog post. However, if javascript is available then jQuery hijacks the form's submit and makes the post via ajax. Well because the comment markup is in a display template, I don't know how to return it from the action method so that jQuery can drop it on the page.
I know how to do this with partial views. I would just have the action method return the right partial view and jquery would append the response to the comment container on the page.
Before I go chopping out my display template in favor of a partial view, is there a straight forward way that I'm missing to send back a display template from the controller?
Here is my action method:
public ActionResult AddComment(PostComment postComment)
{
postComment.PostedDate = DateTime.Now;
postCommentRepo.AddPostComment(postComment);
postCommentRepo.SaveChanges();
if (Request.IsAjaxRequest())
return ???????
else
return RedirectToAction("BlogPost", new { Id = postComment.BlogPostID });
}
When the page loads it doesn't need to worry about it because it uses the templates in the standard way:
<div class="comments">
#Html.DisplayFor(x => x.BlogPost.BlogPostComments)
</div>
I just want to know how I might send a single comment that utilizes the display template back to jQuery.
You may try returning the partial HTML representing the newly posted comment:
if (Request.IsAjaxRequest())
{
return PartialView(
"~/Views/Shared/DisplayTemplates/Comment.cshtml",
postComment
);
}
and on the client side append this comment to the comments container:
$.post('#Url.Action("AddComment")', { ... }, function (result) {
$('#comments').append(result);
// or $('#comments').prepend(result); if you want it to appear on top
});
Does this question give you what you are looking for? Seems to indicate that you can call a HTML helper from an action.
Create a partial view /Shared/DisplayTemplate.cshtml with the following razor code:
#Html.DisplayFor(m => Model)
Then in your controller (or preferably in a base controller class) add a method along these lines:
protected PartialViewResult PartialViewFor(object model)
{
return PartialView("DisplayTemplate",model);
}
In the OP's case then:
public ActionResult AddComment(PostComment postComment)
{
postComment.PostedDate = DateTime.Now;
postCommentRepo.AddPostComment(postComment);
postCommentRepo.SaveChanges();
if (Request.IsAjaxRequest())
return PartialViewFor(postComment);
else
return RedirectToAction("BlogPost", new { Id = postComment.BlogPostID });
}