Unable to download PDF file with Rotativa in MVC4 - asp.net

I am using Rotativa to turn a Razor view into a PDF.
The PDF file is not downloading.
I can see it in Fiddler but the browser is not prompting for download - I have tried this with both IE and Chrome.
I also tried to download the file to a physical path using the solution in this question here. but that didn't work either because of the system couldn't access the folder (Access Denied).
Here is my code:
public ActionResult Index()
{
var model = new CustomerDashboardVM();
return View("Index", model);
}
public ActionResult print(int voucherID)
{
var pdf = new ActionAsPdf("Index", new { voucherID}) { FileName = "testInvoice.pdf", PageSize = Rotativa.Options.Size.A4};
// RotativaHelper.SaveHttpResponseAsFile("http://localhost:65425/BlankDashboard", Server.MapPath("~\\PdfDownloads"));
return pdf;
}
I wonder why is this happening - I click the button, it calls the print ActionResult method - no error messages (I wrapped this in a try and catch block). I have tried this on a colleague PC and it was the same issue!
Many thanks.

The issue was that I was calling the ActionResult print() method on a button click event through an Ajax post. This apparently doesn't work.
It should work if you replace the button with a link, which has the print() mehtod in its URL; i.e., just the way mvc links work..

Okay, i got your mistake. You have not passed parameter name voucherID in Index method.
So now your code look like this:
public ActionResult Index(int voucherID) // Here you have to pass parameter
{
var model = new CustomerDashboardVM(voucherID);
return View("Index", model);
}
and Print() method look like this -
public ActionResult Print(int voucherID)
{
return new ActionAsPdf(
"Index",
new { voucherID = voucherID })
{
FileName = "testInvoice.pdf",
PageSize = Rotativa.Options.Size.A4
};
}

Related

MVC 5 refresh partial view with information from post

Hello I have this puzzle and i would like to share and see if my solution is plausible and possibly get some help.
Basically I have a view called "Create".
Now i click "Escolher Ficheiro" (means "Choose File"), I choose the wanted file and click fill.
So far so good, my file reaches the POST method and its ok at this point.
You can see in the image below that I extract that number from the file and the button "Create" its shown.
However as you can see my "Choose File" input gets null "Nenhum fic..."(means no file selected)
This happens because I return the View Create and it refreshes my whole page.
The thing is that I need to go trhough a POST action on my Controller, so i can read that Prop1.
For obvious security reasons I cannot set a file by default, so I have tried to have some partial views and returning only that partial, but there is something im missing completly. Is there a way of refreshing the "bottom part of the view trhough ajax but going trhough the action on the controller at the same time?
Here is my controller Action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "XL2XMLProcID,SourceXLFiles,Prop1,Prop2,TargetXMLFile,State")] XL2XMLProc xL2XMLProc, HttpPostedFileBase postedFile, string submitButton)
{
if (ModelState.IsValid)
{
if (postedFile != null)
{
// fetch the date from the file
var h = new XLHelper();
var v = h.Fetch("nrContaACreditarRC", postedFile.FileName, #"C:\somefolder\somefolder\somefolder\ExcelSamples\");
if (submitButton == "Create")
{
TestZipAndUpload(v);
}
else
{
// extract postedFile data to show
xL2XMLProc.Prop1 = v;
ViewBag.comingFromFill = true;
return View(ActionName.Create.ToString(), xL2XMLProc);
}
}
else
{
// posted file is null, throw error.
return View();
}
return RedirectToAction(ActionName.Index.ToString());
}
return View(xL2XMLProc);
}
Thank you in advance.

Error to upload file to Amazon S3 for a ASP MVC application

Here is the controller.
I need to upload a image to AWS S3 but I'm get a error . I'm using the MVC project for asp application.
[HttpPost, ValidateInput(false)]
[ValidateAntiForgeryToken]
public ActionResult Nueva(Historia historia, HttpPostedFileBase HeroImagen)
{
try
{
if (ModelState.IsValid)
{
IAmazonS3 client;
using (client = Amazon.AWSClientFactory.CreateAmazonS3Client(_awsAccessKey, _awsSecretKey))
{
var request = new PutObjectRequest()
{
BucketName = _bucketName,
CannedACL = S3CannedACL.PublicRead,
Key = string.Format("UPLOADS/{0}", HeroImagen.FileName),
InputStream = HeroImagen.InputStream
};
client.PutObject(request);
}
historia.HeroImagen = HeroImagen.FileName;
db.Historias.Add(historia);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.AutorID = new SelectList(db.Autores, "AutorID", "AutorNombre", historia.AutorID);
return View(historia);
}
catch (Exception)
{
return View();
}
}
But, when I submit the form get an error.
.
For me it look like your AWS related code is not even running.
You get an error based on the line "Viewbag.AutorID = ...", which means, the redirect command above it was never running. For me it looks like your ModelState is invalid.
Note: Please copy your code and exception to your question as text, that would make your question searchable.

MVC4 - ContextDependentView - What does it mean?

I have just started using MVC4 and the first action method that I look at has something new. I checked out the internet and can't find anything about this:
public ActionResult LogOn()
{
return ContextDependentView();
}
Does anyone know what a ContextDependentView is ?
Something new to me.
It's purpose is to facilitate View or PartialView action results for the Login and Register actions.
private ActionResult ContextDependentView()
{
string actionName = ControllerContext.RouteData.GetRequiredString("action");
if (Request.QueryString["content"] != null)
{
ViewBag.FormAction = "Json" + actionName;
return PartialView();
}
else
{
ViewBag.FormAction = actionName;
return View();
}
}
Like other things in MVC it is done by convention... the convention here is when the Request.QueryString contains a ?content=xxxx, it prepends "Json" to the action name, stuffs it a ViewBag property and returns the partial version of the View. For example:
A request for /Account/Login?content=test would be resolved to ViewBag.FormAction = "JsonLogin"; and then return a partial.
A request for /Account/Login has no content query string so its form action remains ViewBag.FormAction = "Login";

How to use FilePathResult.WriteFile?

Background
I have a secured folder containing secret report files (in pdf format). Each file corresponds to a single user.
My site is developed using Asp.net MVC 3 Razor.
When a user navigate to http://mydomain.com/UserProfile/Report, it invokes the GET-handling action method Report and return a view with a submit button Download Report.
When the user click the button, it invokes the POST-handling action method. Verification will be done in this action method. When the verification is successfully passed, the action method returns the requested file.
Question
Could you give me an example how to implement the POST-handling action method?
Here is the skeleton:
[HttpPost]
public ActionResult Report(/*any parameter I don't know*/)
{
if(!IsAuthenticated())
return RedirectToActionLink("SomeActionMethod","SomeController");
else
{
// what should I do here?
// Asssume my secret folder is d:\mydomain.com\secret and the public folder is d:\mydomain.com\httpdoc
}
}
Here is how you can return a file back to the client:
public FileContentResult Report(/*any parameter I don't know*/)
{
if(!IsAuthenticated())
return RedirectToActionLink("SomeActionMethod","SomeController");
else
{
// Read the file from your location into a byte array named content
Response.ContentType = "application/pdf";
return new FileContentResult(content, "application/pdf");
}
}
You can use the File method to return a FileContentResult
[HttpPost]
public FileContentResult Report()
{
if(!IsAuthenticated())
return RedirectToActionLink("SomeActionMethod","SomeController");
else
{
string path = #"d:\mydomain.com\secret\" + fileName;
return File(path, "application/pdf"); ////
}
}

RedirectToAction usage in asp.net mvc

I want to post some questions about ASP.Net MVC. I am not familiar with web developing, But I was assigned to the web part of a project. We are doing the following: first, we create get & set properties for the person data:
public class Person
{
public int personID {get;set;}
public string personName {get;set;}
public string nric {get;set;}
}
and after login, we put the data in a class Person object and we use RedirectToAction like this:
return RedirectToAction("profile","person",new { personID = Person.personID});
It's working normally, but the parameter are shown in the URL. How can I hide them and also
can I hide the action name? Guide me the right way with some examples, please.
The parameter are shown in the URL because that is what the third parameter to RedirectToAction is - the route values.
The default route is {controller}/{action}/{id}
So this code:
return RedirectToAction("profile","person",new { personID = Person.personID});
Will produce the following URL/route:
/Person/Profile/123
If you want a cleaner route, like this (for example):
/people/123
Create a new route:
routes.MapRoute("PersonCleanRoute",
"people/{id}",
new {controller = "Person", action = "Profile"});
And your URL should be clean, like the above.
Alternatively, you may not like to use ID at all, you can use some other unique identifier - like a nickname.
So the URL could be like this:
people/rpm1984
To do that, just change your route:
routes.MapRoute("PersonCleanRoute",
"people/{nickname}",
new {controller = "Person", action = "Profile"});
And your action method:
public ActionResult Profile(string nickname)
{
}
And your RedirectToAction code:
return RedirectToAction("profile","person",new { nickname = Person.nickname});
Is that what your after?
If you don't want the parameter to be shown in the address bar you will need to persist it somewhere on the server between the redirects. A good place to achieve this is TempData. Here's an example:
public ActionResult Index()
{
TempData["nickname"] = Person.nickname;
return RedirectToAction("profile", "person");
}
And now on the Profile action you are redirecting to fetch it from TempData:
public ActionResult Profile()
{
var nickname = TempData["nickname"] as string;
if (nickname == null)
{
// nickname was not found in TempData.
// this usually means that the user directly
// navigated to /person/profile without passing
// through the other action which would store
// the nickname in TempData
throw new HttpException(404);
}
return View();
}
Under the covers TempData uses Session for storage but it will be automatically evicted after the redirect, so the value could be used only once which is what you need: store, redirect, fetch.
this may be solution of problem when TempData gone after refresh the page :-
when first time you get TempData in action method set it in a ViewData & write check as below:
public ActionResult Index()
{
TempData["nickname"] = Person.nickname;
return RedirectToAction("profile", "person");
}
now on the Profile action :
public ActionResult Profile()
{
var nickname = TempData["nickname"] as string;
if(nickname !=null)
ViewData["nickname"]=nickname;
if (nickname == null && ViewData["nickname"]==null)
{
throw new HttpException(404);
}
else
{
if(nickname == null)
nickname=ViewData["nickname"];
}
return View();
}
Temp data is capable of handling single subsequent request. Hence, value gone after refresh the page. To mitigate this issue, we can use Session variable also in this case. Try below:
public ActionResult Index(Person _person)
{
Session["personNickName"] = _person.nickName;
return RedirectToAction("profile", "person");
}
And in "profile" actionmethod:
public ActionResult profile()
{
Person nickName=(Person)Session["personNickName"];
if(nickName !=null)
{
//Do the logic with the nickName
}
}

Resources