I need help in uploading a file to a folder on my server and then adding the file details to a database - sql

I am trying to make a page for my site where users can upload a game, give it a name then the file gets uploaded to a folder on my site and the file name and game name get added to my sql database but it gives an error saying: "System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index" when i try to run it.
My code for this page is:
#{
var db= Database.Open("Games");
var sqlQ = "SELECT * FROM Games";
var data = db.Query(sqlQ);
}
#{
var fileName = "";
if (IsPost) {
var fileSavePath = "";
var uploadedFile = Request.Files[0];
fileName = Path.GetFileName(uploadedFile.FileName);
fileSavePath = Server.MapPath("~/App_Data/UploadedFiles/" +
fileName);
uploadedFile.SaveAs(fileSavePath);
}
var GameName="";
var GameGenre="";
var GameYear="";
if(IsPost){
GameName=Request["formName"];
var SQLINSERT = "INSERT INTO Games (Name, file_path) VALUES (#0, #1)";
db.Execute(SQLINSERT, GameName, fileName);
Response.Redirect("default.cshtml");
}
}
<h1 >Add a new game to the database</h1>
<form action="" method="post">
<p>Name:<input type="text" name="formName" /></p>
#FileUpload.GetHtml(
initialNumberOfFiles:1,
allowMoreFilesToBeAdded:false,
includeFormTag:true,
uploadText:"Add")
The error page says that the problem is with line 11 but i don't know what to change.

As Hightechrider has correctly said, your code should reside in Controllers, not in views. The exception you are getting is because Request.Files is an empty array, so when you're trying to access [0] element, you get an IndexWasOutOfRange error.
I'd recommend you reading the following article for uploading files in ASP.NET MVC. It presents an easier, more consistent and flexible model by putting the code in the controller action. Basically, all code boils down to this:
You create an upload form with submit button and file input.
You create an action that accepts HttpPostedFileBase variable.

You must set the proper enctype to your form if you want to upload files:
<form action="" method="post" enctype="multipart/form-data">

Related

Not able to read string value from cshtml.cs page in .cshtml page in ASP.NET Core 6.0

I am new to ASP.NET Core 6.0 and I am facing an issue while reading a value from .cshtml.cs file in .cshtml page.
I have tried to use the [BindProperty] attribute and also tried to bind value in ViewData.
Basically, I have created an HTML Table and bound it to a string value. Please find below the sample code that I tried.
cshtml.cs code:
[BindProperty]
public string HTMLRep { get; set; }
HTMLRep = reportHTML; //reportHTML has the HTML Table in the post ActionMethod
I also tried
ViewData["HTML"] = reportHTML
.cshtml markup:
#{
var val = ViewData["HTML"];
}
<panel>
#Model.HTMLRep
//Also tried -
#val
<panel>
Any help on this will be very useful. Thank you
By default, if you try to use HTML text for output it encodes it. So you have to write like following:
<panel>
#Html.Raw(Model.HTMLRep)
<panel>
This should fix your issue.
If I would you then might be solve this issue in following manner.
Web Site Dynamic Content From Backend:
[HttpGet]
public IActionResult BindDynamicContentToHtmlCard()
{
var convertedHtmlBodyList = new List<string>();
for (int i = 1; i < 10; i++)
{
StringBuilder sb = new StringBuilder();
var convertedHtmlBody = "";
sb.Append("<!DOCTYPE html>");
sb.Append("<html>");
sb.Append("<head>");
sb.Append("</head>");
sb.Append("<body>");
sb.Append("<h5 class='card - title' style='border: solid'><strong>TEST WEB SITE "+ i + " </strong></h5>");
sb.Append("<p>Simplest solution of the dynamic card generation.</p>");
sb.Append("<p>This is how you can generate dynamic Card</p>");
sb.Append("<p><strong style='color: red'>Note:</strong> For more details please check details: <a href='https://stackoverflow.com/questions/71167733/i-want-to-use-html-rawstring-where-string-contains-a-complete-html-webpage'>Details</a></p>");
sb.Append("</body>");
sb.Append("</html>");
convertedHtmlBody = sb.ToString();
convertedHtmlBodyList.Add(convertedHtmlBody);
}
ViewBag.bindToHtmlInView = convertedHtmlBodyList;
return View(); ;
}
Panel HTML:
#{
ViewData["Title"] = "BindDynamicToHtml";
}
<div class="row">
<div class="col-md-12">
#foreach (var item in ViewBag.bindToHtmlInView)
{
<panel>
#Html.Raw(item)
</panel>
}
</div>
</div>
Panel Output:
Here you can get the panel element.

SelectPDF for .Net :DllNotFoundException: Unable to load DLL 'libgdiplus': The specified module could not be found

I am trying to generate pdf from html. I am using SelectPdf for .Net.
When I try to generate pdf, I get this error:
DllNotFoundException: Unable to load DLL 'libgdiplus': The specified
module could not be found.
My primary Guide is This Documentation on their official website
SettingsController.cs
[Route ("settings/aaa")]
public IActionResult GeneratePdf () {
return View ();
}
[HttpPost]
[Route ("settings/aaa")]
public IActionResult GeneratePdf (IFormCollection collection) {
// read parameters from the webpage
string htmlString = collection["TxtHtmlCode"];
string baseUrl = collection["TxtBaseUrl"];
int webPageWidth = 1024;
int webPageHeight = 1280;
// instantiate a html to pdf converter object
HtmlToPdf converter = new HtmlToPdf ();
converter.Options.PdfPageOrientation = PdfPageOrientation.Portrait;;
converter.Options.WebPageWidth = webPageWidth;
converter.Options.WebPageHeight = webPageHeight;
// create a new pdf document converting an url
PdfDocument doc = converter.ConvertHtmlString (htmlString, baseUrl);
// save pdf document
byte[] pdf = doc.Save ();
// close pdf document
doc.Close ();
// return resulted pdf document
FileResult fileResult = new FileContentResult (pdf, "application/pdf");
fileResult.FileDownloadName = "Document.pdf";
return fileResult;
}
GeneratePdf.cshtml
<div>
<form method="post" asp-controller="Settings" asp-action="GeneratePdf">
<input value="stuff" name="TxtHtmlCode"/>
<input value="" name="TxtBaseUrl"/>
<input type="submit" value="submit">
</form>
</div>
My goal is to make SelectPdf generate pdf from "TxtHtmlCode" input.

MVC4 C# - How to submit list of object that are being displayed to the user?

I'm working on an MVC4 C# project in VS2010.
I would like to allow the user to upload the contents of a .csv file to a database but there is a requirement to first echo the contents of the file to screen (as a final visual check) before submitting. What would be the best approach of submitting to the database as I am struggling to find a way of persisting the complex object in the view?
Here is the view where I am using a form to allow the user to upload the csv file:
#model IEnumerable<MyNamespace.Models.MyModel>
#{
ViewBag.Title = "Upload";
WebGrid grid = new WebGrid(Model, rowsPerPage: 5);
}
<h2>Upload</h2>
<form action="" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" />
</form>
<h2>Grid</h2>
#grid.GetHtml(
//Displaying Grid here)
<p>
#Html.ActionLink("Submit", "Insert")
</p>
Here is the action in the controller that processes the csv file:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
file.SaveAs(path);
//Stream reader will read test.csv file in current folder
StreamReader sr = new StreamReader(path);
//Csv reader reads the stream
CsvReader csvread = new CsvReader(sr);
List<MyModel> listMyModele = new List<MyModel>(); // creating list of model.
csvread.Configuration.RegisterClassMap<MyModelMap>(); // use mapping specified.
listMyModel = csvread.GetRecords<MyModel>().ToList();
sr.Close();
//return View();
return View(listMyModel);
}
Up until this point everything is simple, I can upload the csv to the controller, read using CsvHelper, produce a list of MyModel objects and display in the view within a grid. To reiterate my initial question, is it now possible to submit the complex object (the list of MyModel) from the view as I can't figure out a way of making it available to an action within the controller.
Thank you.
Yes it's possible, It's "easier" if you have a Model with the IEnumerable in it so you can use the naming convention like this:
Property[index].ItemProperty
for every Html input/select field.
If you want to keep the IEnumerable as Model I think the naming convention is something like this:
ItemProperty[index]
So translated in code:
#Html.TextBoxFor(t => t.Property, new { name = "Property[" + i + "]" })
where i comes from a for loop to render all items or something like that.
I have already done it but I can't find the code at the moment. KendoUI uses this scheme for its multirows edit in the grid component.
You can check their POST AJAX requests for the right naming convention.
EDIT 1:
Otherwise you can think about store the model somewhere temporarily and retrieve it every time and updating with user inputs. It's a little more expensive but probably easier to write. Something like an updated csv file or a temporary db table.

First run FileResult to download file, then RedirectToAction

This will send an email when a button gets pushed. However I am trying to call the FileResult, SaveDocument, to download a file right before redirecting back to the button page.
I am using a hardcoded file for now to download for the sake of testing. I can run the SaveDocument() result using a test button. I can't send an email, run the SaveDocument Action and then redirect.
[HttpGet]
public ActionResult send(int thisbatch, string listofpositives)
{
MailMessage mail = new MailMessage();
SmtpClient smtpServer = new SmtpClient("smtperServer");
smtpServer.Port = 25; // Gmail works on this port
smtpServer.EnableSsl = false;
mail.From = new MailAddress("xxxe#xxx.com");
mail.To.Add("xxxe#xxx.com");
mail.Subject = "Batch Closed";
mail.Body="some info stuff here";
smtpServer.Send(mail);
SaveDocument();
return RedirectToAction("AddColiform");
}
//THIS WORKS BY ITSELF CALLED FROM A BUTTON
public FileResult SaveDocument()
{
string filePath = Server.MapPath("~/XML_positives/Test1.xml");
string contentType = "text/xml";
return File(filePath, contentType, "Test1.xml");
}
Well, no solution was found (so far) to download a file and RedirectToAction back to the initial page in the same ActionResult. If someone can come up with a better answer I will take this one off.
So based on contents of string "listofpositives" I call a new View "Has Positives" with 2 buttons: One calls the FileResult Action and one redirects back to where everything started (this is desired).
A lot clunkier than just popping up a File Save As dialog and then moving on automatically. But I need to build something and move on. I feel sorry for my users. oh well.
Here is the code after I send an email and return to desired view:
if (listofpositives == "")
{
return RedirectToAction("AddColiform");
}
else
{
return RedirectToAction("HasPositives",new { thisbatch=thisbatch, listofpositives=listofpositives});
}
Here is the code for the whole extra view:
#{
ViewBag.Title ="HasPositives" ;
}
<h2>HasPositives</h2>
<p>Batch: #ViewData["batchid"] </p>
<p>Postives: #ViewData["listofpositives"]</p>
<br /><br />
Process your XML file using XMLSampling<br /><br /><br />
<button onclick="location.href='#Url.Action("SaveDocument", "Home")';return false;">Download Positive XML File</button>
<button onclick="location.href='#Url.Action("AddColiform", "Home")';return false;">Done</button>

Razor / Webmatrix / SQL: Update Textarea

I am trying to implement an short bio form where each user could edit and update its bio. Based on the fact that if the user has filled the form before or not, the previous text or nothing, gets returned as an initial text in the Textarea.
Here is the block I have for taking the username from the keyboard, searching the dbase for a value and trying to output it on the textarea before the form gets submitted by the user.
A kind of profile memory if you like.
#{
Validation.RequireField("currentuser");
Validation.Add("bioprint", Validator.StringLength(3000, 0, "Your bio should not exceed 3000 characters"));
var init = "";
var currentuser = Request["currentuser"];
var db = Database.Open("ResearchA");
var cbio = db.QuerySingle("SELECT bios FROM usernamesb WHERE username = #0",currentuser); //get current bio string
if (cbio == null) {init = cbio;} //check if string is NULL
else {init = "Tell us about you...";}
if(IsPost && Validation.IsValid()) {
var userbio = #Request["Bio"];
var insertbio = "UPDATE usernamesb SET bios = #0 WHERE username = #1";
db.Execute(insertbio, userbio, currentuser); //Update database with a new entry.
}
}
And here is how I have my controls setup in the HTML block:
<input type="text" name="currentuser" id="currentuser" value="#Request.Form["currentuser"]"/>
<textarea name="Bio" rows="10" cols="50" placeholder ="#cbio"></textarea>
However I dont get the already existing string output.
Thanks a lot for the interest guys!!
Your cbio variable is currently being loaded with a single row from the database. You need to get one of the fields from that row. Two ways of doing that, either change your database query to be:
var cbio = db.QueryValue("SELECT bios FROM usernamesb ...
which will return just the string. Or leave your database query the same, and change your way of accessing the field from the row by changing the html part:
<textarea name="Bio" rows="10" cols="50">#cbio.bios</textarea>
If you want to set the text in a <textarea> you put the value to be displayed between the opening and closing tags:
<textarea name="Bio" rows="10" cols="50">#cbio</textarea>