The below given codes works perfect for me when i am using it with pure asp.net(aspx) application having redirection and front end in asp net.
Now my scenario is, i have mixed mode application in mvc and asp.net(aspx page)
so i am simply using same page(aspx) for downloading file by calling it from mvc controller method, which is not working .
i have written ajax call in view to call a void method in controller which redirects to aspx page where this code is written , rest of case is as mentioned above.
**string path = HttpContext.Current.Server.MapPath("~/Reporting/OnePager.xlsm");
string id = Request.Params["id"];
HttpResponse response = this.Response;
response.Buffer = true;
response.Clear();
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("content-disposition", "attachment; filename=" + id + "-One-Pager.xlsm");
response.WriteFile(path);
response.Flush();
response.End();**
Here is ajax call
if (arrselected.length > 0) {
$.ajax({
type: 'POST',
url: '#Url.Action("ExportProjectOnePager", "controller")',
dataType: 'json',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ ID: arrselected[0]}),
success: function (output) {
if (output.notValid.length != arrselected.length) {
alert("success");
}
if (output.notValid != "") {
alert("You do not have permission to see this IDs :" + output.notValid);
}
}
});
}
and here is void controller method
public void ExportProjectOnePager(string ID)
{
string _Path = #"~/Reporting/ProjectOnePager.aspx?id=" + ID;
Response.Redirect(_Path);
}
You can do the same in the controller method, but you have to change it to return FileResult or FileStreamResult, and copy the code there.
You can also change the controller method to return RedirectResult and inside the code use return Redirect('the aspx page') instead of Response.Redirect and return type is void
Related
I have an MVC .cshtml page with a button. It's in a grid and I am passing the row ids to the controller using the jquery
<button type="submit" id="btn_View" name="view"
class="btn_View">
$(".btn_View_Question").click(function () {
var json = [];
var obj = {};
var rowID = $(this).closest('tr').attr('id');
obj.RowId= rowID ;
console.log(obj);
json.push(obj)
var responseDetails = JSON.stringify(json);
$.ajax({
url: "/Home/View",
type: "POST",
data: responseDetails,
dataType: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
});
});
In the controller class I am redirecting to a aspx report page as follows
public RedirectResult ViewQuestionnaire(string[] id)
{
var reportParameters = new Dictionary<string, string>();
reportParameters.Add("ID", id[0]);
Session["reportParameters"] = reportParameters;
return Redirect("../Reports/ViewQuestionarie.aspx");
}
The aspx page is not loading. When I debug it the page_load of the aspx page also executing. What might the wrong thing I am doing here
Redirect is going to return a 302 response with the new url as the location header value.You should not be making the call to an action method which returns a 302 response from an ajax call.
Looks like you want to set some data to Session. You may use your ajax call to still do that part. Instead of returning a 302 response,return a json data structure with the url you want the browser to be redirected.
public ActionResult ViewQuestionnaire(string[] id)
{
var reportParameters = new Dictionary<string, string>();
reportParameters.Add("ID", id[0]);
Session["reportParameters"] = reportParameters;
return Json(new {status = "success", url="../Reports/ViewQuestionarie.aspx"});
}
And in the success / done event of the ajax call, you can read the url property of the json response coming back and use that to do the redirection.
$.ajax({
//Omitted some parameters
success: function(res) {
if (res.status === "success") {
window.location.href = res.url;
}
}
});
im experiencing a weird problem.
I work with MVC (not web api), so the controller inherits from Controller, not from ApiController.
Im calling a controller action (POST) with ajax, and the action is returning HttpResponseMessage
This is the response i get:
{"readyState":4,"responseText":"StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StringContent, Headers:\r\n{\r\n Location: /\r\n Content-Type: application/json; charset=utf-8\r\n}","status":200,"statusText":"OK"}
However, when ajax receives the data, it fires the fail method.
This is the ajax function:
$.ajax({
url: "someurl",
type: "post",
data: data,
dataType: "json",
contentType: "application/json; charset=utf-8"
}).done(function (data) {
alert(data.responseText);
window.location.href = "redirect to some url";
}).fail(function (data) {
alert("error");<-- this one is called even when i set HttpStatusCode.OK
alert(JSON.stringify(data));
}).always(function () {
});
This is a simplified controller action:
[HttpPost]
[AllowAnonymous]
public HttpResponseMessage Index(HttpRequestMessage request, Login model)
//public HttpResponseMessage Index(Login model) // i get the same with any of these 2
{
HttpResponseMessage response = new HttpResponseMessage();
string message = "";
if (something)
{
response.StatusCode = HttpStatusCode.OK;
FormsAuthentication.SetAuthCookie(model.UserName, true);
currentUser.LastLoginDate = DateTime.Now;
currentUser.FailedPasswordAttemptCount = 0;
ModelRepositories.MobileCommerceRepository.SaveChanges();
}
else
{
message = "User does not exist. The user name or password provided is incorrect.";
response.StatusCode = HttpStatusCode.BadRequest;
}
//response = request.CreateResponse(HttpStatusCode.OK);
string json = JsonSerializer.SerializeToString(message);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
}
If i do the same ajax call to web api controller instead (with the same C# code inside), it fires success. What is the difference ?
Thanks
You cannot use HttpResponseMessage with an MVC action. Web API and MVC are two different frameworks, you can't mix and match pieces of them.
Just putting my answer if anyone is still looking. I agree with previous post as MVC will not return actual content. Instead I used
public async Task<string> GetAjaxCollateralSummary(string id)
{
//your logic
return JsonConvert.SerializeObject(result);
}
and the in my js page I have following code:
$.post(url, { id: '2' })
.success(function (response) {
console.log(response);
var jsondResult = JSON.parse(response);
}
)
.error(function (err) {
console.log("Error while trying to get data from MVC controller ");
console.log(err);
})
When I try to Download file via ajax json MVC controller not working. not getting the MIME response. Just renders as text in window. I tried all options mentioned in forums but no luck. Please help.
The controller sends the proper file back but the javascript ajax renders it as json I think. I want to get the "Save" or "Open" file response header prompt for file when I click the download button.
$("#btnDownloadEDIFile").bind("click", function (e)
{
e.preventDefault();
displayAjaxLoading(true);
$.ajax({
type: 'POST',
dataType: "json",
async: false,
contentType: 'application/json; charset=utf-8',
url: '#Url.Action(MVC.AccountsPayable.StagedInvoice.DownloadFile())',
data: JSON.stringify({ StagedFileId: $('#StagedFileId').val() , FilePath: $('#FilePath').val() , SourceFileName: $('#SourceFileName').val() }),
success: function (result) {
//alert(result);
if (result != "") {
displayNotoficationError([result]);
}
else {
}
},
error: function (result) {
//debugger;
alert(result);
displayNotoficationError([result]);
}
});
});
When I execute this it renders as text on window and also throws a ajax error in javascript.
Here's controller code
public virtual ActionResult DownloadFile(Nullable<int> StagedFileId, string FilePath, string SourceFileName)
{
string _FullPath = _WebApplicationConfiguration.SourceStagedInvoiceFileFolder + FilePath;
if (System.IO.File.Exists(_FullPath))
{
HttpContext.Response.ClearContent();
HttpContext.Response.ContentType = "application/octet-stream";
HttpContext.Response.AddHeader("content-disposition",
"attachment; filename=" + SourceFileName);
HttpContext.Response.BinaryWrite(System.IO.File.ReadAllBytes(_FullPath));
return File(_FullPath, "text/octet-stream", SourceFileName);
}
else
{
return Content("");
}
}
I know this is not exactly what you are trying to do, but I have been pretty happy with a totally different approach. This method will force the Download/Open dialog no matter how the file is linked to or what browser is used. All you have to do is make sure all the files that you want this behavior on must be in a specified folder, in this case /Library.
Add this to your Global.asax file in either classic Asp.Net or MVC.
protected void Application_BeginRequest()
{
if (Request.Path.Contains("/Library/") && (File.Exists(Request.PhysicalPath)))
{
var fileInfo = new FileInfo(Request.PhysicalPath);
Response.Clear();
Response.TransmitFile(Request.Path);
Response.AddHeader("Content-Disposition", "attachment;filename=" + fileInfo.Name);
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.Flush();
Response.End();
}
}
I got the idea for this from this site, but I can't find the link to give credit. Sorry.
I've got a controller action that downloads a dynamically generated file:
public ActionResult DownloadFile()
{
var obj = new MyClass { MyString = "Hello", MyBool = true };
var ser = new XmlSerializer(typeof(MyClass));
var stream = new MemoryStream();
ser.Serialize(stream, obj);
stream.Position = 0;
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=myfile.xml");
Response.ContentType = "application/xml";
// Write all my data
stream.WriteTo(Response.OutputStream);
Response.End();
return Content("Downloaded");
}
Just for reference:
public class MyClass
{
public string MyString { get; set; }
public int MyInt { get; set; }
}
This is working, and the file (myfile.xml) is downloaded.
However, the message "Downloaded" is not sent to the browser.
Similarly, if I replace return Content("Downloaded");
for return Redirect("www.something.com");
then the browser is redirected before the file downloads.
As a bit of a pre-amble, the user journey is:
User fills out form on previous view
Form is submitted
XML is generated and downloaded
User is redirected / "Downloaded" view is shown (so hitting F5 won't re-post the form)
As Ross has said, you can only return one response to a HTTP request.
What i do in that case is:
Send the request to the server
The server generates the file and stores it in some server side data structure (Cache, Usersession, TempData)
The server returns a RedirectToAction() (POST, REDIRECT, GET pattern)
The redirected action returns a View with some javascript which
Triggers the download of the pregenerated file by setting window.location.href property to an special download action which sends the file back to the browser
Each HTTP request can only have one response - you're trying to sneak in two (the file, and a page).
Normally when you send a "Content-Disposition: attachment" HTTP header the browser will stay on the current page and pop a file save dialog (or automatically save the file in your downloads).
You're going to have to change your strategy if you want to prevent re-submission of the form. I'd suggest a bit of javascript to disable the form's submit button and show the "Completed" message in a div overlay?
Here is how I redirected after the file is downloaded.
The main logic is to wait the redirect until the file is downloaded.
To do that, a server side response is calculated and redirect is delayed using server side response time + some offset.
Server Side Controller Code:
[HttpPost]
public ActionResult GetTemplate()
{
return Json(new {Url = Url.Action("ReturnTemplate") });
}
[HttpGet]
public ActionResult ReturnTemplate()
{
FileResult fileResult = // your file path ;
return fileResult;
}
Client Side Code:
<div id="btnGen" align="right"><button class="main-button" id="generateTemplate" type="Submit"></div>
Javascript:
$("#generateTemplate").click(function () {
var startTime = (new Date()).getTime(), endTime;
$.ajax({
url: '#Url.Action("GetTemplate", "Controller")',
type: 'POST',
traditional: true,
dataType: "json",
contentType: "application/json",
cache: false,
data: JSON.stringify(),
success: function (result) {
endTime = (new Date()).getTime();
var serverResponseTime = endTime - startTime + 500;
setInterval(function () { Back() }, serverResponseTime);
window.location = result.Url;
}
});
});
function Back() {
window.location = '#Url.Action("Index","Controller")';
}
I use $.ajax() to poll an action method every 5 seconds as follows:
$.ajax({
type: 'GET', url: '/MyController/IsReady/1',
dataType: 'json', success: function (xhr_data) {
if (xhr_data.active == 'pending') {
setTimeout(function () { ajaxRequest(); }, 5000);
}
}
});
and the ActionResult action:
public ActionResult IsReady(int id)
{
if(true)
{
return RedirectToAction("AnotherAction");
}
return Json("pending");
}
I had to change the action return type to ActionResult in order to use RedirectToAction (originally it was JsonResult and I was returning Json(new { active = 'active' };), but it looks to have trouble redirecting and rendering the new View from within the $.ajax() success callback. I need to redirect to "AnotherAction" from within this polling ajax postback. Firebug's response is the View from "AnotherAction", but it's not rendering.
You need to consume the result of your ajax request and use that to run javascript to manually update window.location yourself. For example, something like:
// Your ajax callback:
function(result) {
if (result.redirectUrl != null) {
window.location = result.redirectUrl;
}
}
Where "result" is the argument passed to you by jQuery's ajax method after completion of the ajax request. (And to generate the URL itself, use UrlHelper.GenerateUrl, which is an MVC helper that creates URLs based off of actions/controllers/etc.)
I know this is a super old article but after scouring the web this was still the top answer on Google, and I ended up using a different solution. If you want to use a pure RedirectToAction this works as well. The RedirectToAction response contains the complete markup for the view.
C#:
return RedirectToAction("Action", "Controller", new { myRouteValue = foo});
JS:
$.ajax({
type: "POST",
url: "./PostController/PostAction",
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
complete: function (result) {
if (result.responseText) {
$('body').html(result.responseText);
}
}
});
C# worked well
I just changed the JS because responseText was not working for me:
$.ajax({
type: "POST",
url: posturl,
contentType: false,
processData: false,
async: false,
data: requestjson,
success: function(result) {
if (result) {
$('body').html(result);
}
},
error: function (xhr, status, p3, p4){
var err = "Error " + " " + status + " " + p3 + " " + p4;
if (xhr.responseText && xhr.responseText[0] == "{")
err = JSON.parse(xhr.responseText).Message;
console.log(err);
}
});
You could use the Html.RenderAction helper in a View:
public ActionResult IsReady(int id)
{
if(true)
{
ViewBag.Action = "AnotherAction";
return PartialView("_AjaxRedirect");
}
return Json("pending");
}
And in the "_AjaxRedirect" partial view:
#{
string action = ViewBag.ActionName;
Html.RenderAction(action);
}
Reference:
https://stackoverflow.com/a/49137153/150342