Reading from a textfile in MVC - asp.net-mvc

I have recently tried to read from a textfile and populate the db and then display the populated data onto my MVC application. Reason for all of this is because I want my desktop application to be able to pass data to my MVC application and save it into my MVC db.
This is what I have:
public ActionResult Index([Bind(Include = "location_id,location_name")] Location location)
{
string full_path = Request.MapPath("~/App_Data/TestText.txt");
if (System.IO.File.Exists(full_path))
{
if (new System.IO.FileInfo(full_path).Length > 0)
{
string[] text_file = System.IO.File.ReadAllLines(HostingEnvironment.MapPath(#"~/App_Data/TestText.txt"));
foreach (string record in text_file)
{
string[] record_cell = record.Split('~');
location.location_name = record_cell[1];
db.Locations.Add(location);
db.SaveChanges();
}
System.IO.File.WriteAllText(HostingEnvironment.MapPath(#"~/App_Data/TestText.txt"), "");
}
}
ViewBag.location_id = new SelectList(db.Locations, "location_id", "location_name");
return View();
}
I have the code above which is placed in my home controller so that everytime the page loads it looks into the textfile for new data and stores it in the db, and at the same time returns a view to display the index page.
Everything works fine on localhost however when hosted I am getting the following error:
I have my textfile located in App_Data, I however feel as though placing the code in the controller under Index is causing this. Can you please help me out to show me where to place the code so that on startup of the website it checks for updated datab in the textfile.
Update:
I have found the error causing the site not to load. Somehow the following line of code from the view, which is populating a dropdown list with data from the db is not working:
#Html.DropDownList("location_id", null, htmlAttributes: new { #class = "form-control"})
Any solutions on fixing this?

Related

Display image from byte array in ASP.NET MVC Core

I have a byte[] stored in a VARBINARY(MAX) column in a table in my database.
I want to show this image on my index.cshtml page - but I'm stuck.
My CSHTML looks like this:
#using Microsoft.AspNetCore.Hosting.Internal
#{
ViewData["Title"] = "Title";
}
<h2>#ViewData["Title"]</h2>
<h3>#ViewData["Message"]</h3>
#if (!Context.User.Identity.IsAuthenticated)
{
<p>blah blah.</p>
<p>blah blah</p>
}
#if (Context.User.Identity.IsAuthenticated)
{
<p>Hi #(Context.User.Identity.Name)<br/></p>
<p>Where we off to today?</p>
}
I want to add
<img src="...." />
obviously I don't know what to do here.
My model has the byte array data:
public byte[] UserImage { get; set; }
My controller assigned that the value:
var model = new IndexViewModel
{
Username = user.UserName,
Email = user.Email,
PhoneNumber = user.PhoneNumber,
IsEmailConfirmed = user.EmailConfirmed,
StatusMessage = StatusMessage,
UserImage = user.UserImage
};
but I am using .net core in VS2017 and the answers I have found don't seem to work for me. Any help would be really appreciated.
Thanks
Johan
You have two options:
Base64 encode the byte[] and use a Data URI:
<img src="data:image/png;base64,[base64-encoded byte array here]">
However, bear in mind two things. 1) Data URIs are supported in every modern browser, but notoriously do not work in IE 10 and under. That may not be an issue, but if you need to have legacy IE support, this is a non-starter. 2) Since you're Base64-encoding, the size of the "image" will balloon roughly 50%. As such, Data URIs are best used with small and simple images. If you've got large images or simply a lot of images, your HTML document can become a very large download. Since Data URIs are actually embedded in the HTML code, that means the browser cannot actually begin to render the page at all until the entire HTML document has loaded, which then also means that if it's megabytes in size, your users will be waiting a while.
Create an action that pulls the image from the database and returns it as a FileResult. This is the most optimal path. Essentially, you just need an action that accepts some sort of identifier for the image, which can be used to pull it from the database. You then return the byte[] like:
return File(myByteArray, "image/png");
In your view, you simply make the image source the route to this action:
<img src="#Url.Action("GetImage", "Foo", new { id = myImageIdentifier }">
Ok so I managed to work it out with the help above. I created a method on the controller that looks like this:
public FileResult GetFileFromBytes(byte[] bytesIn)
{
return File(bytesIn, "image/png");
}
[HttpGet]
public async Task<IActionResult> GetUserImageFile()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return null;
}
FileResult imageUserFile = GetFileFromBytes(user.UserImage);
return imageUserFile;
}
in my cshtml I then added this:
<img src= '#Url.Action("GetUserImageFile", "Manage")'/>
"Manage" was the start of the controller name. I didnt need to pass in an ID as my image bytes are stored on the aspuser so the code knows which user it is using the GetUserAsync
Can anyone see problems with this? Also, it doesnt seem to care that the origional image is a jpeg but in the code I am using "image/png", am I risking losing something?
Many thanks for the comments and help! this is such an amazing forum!

Can i download a pdf file saved in media in Umbraco

I need to set create a page on which i have button and on clicking, it should redirect to a registration page and then download a pdf file. so i created a document type in Umbraco which have a file Upload field and i uploaded one file through it. On its template i have added a macro which have a partial view for the registration page. After completing registration, this pdf file should download automatically.
My problem is, the file i uploaded is not showing in the Media library. but the Url is as follows: /media/1051/filname.pdf .
am getting this url in controller. but couldn't get the file usinng its id.
[HttpPost]
public HttpResponseMessage DownloadFile([FromBody] DownloadEBookViewModel model)
{
int id = Convert.ToInt32(model.Url.Split('/')[2]);
var media = Umbraco.Media(id).Url;
if (!File.Exists(media))
throw new HttpResponseException(HttpStatusCode.NotFound);
HttpResponseMessage Response = new HttpResponseMessage(HttpStatusCode.OK);
byte[] fileData = File.ReadAllBytes(media);
if (fileData == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
Response.Content = new ByteArrayContent(fileData);
Response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return Response;
}
Someone please help. thank you
When working with the Umbraco helper in code behind, I would advise to use the typed variants for getting items
var media = Umbraco.TypedMedia(id).Url;
This will give you a strongly typed model with intellisense
To get the physical file from the media object you'll probably want to call
byte[] fileData = File.ReadAllBytes(media.getPropertyValue("umbracoFile"));
instead of:
byte[] fileData = File.ReadAllBytes(media);
(code is untested)

how to pass a folder path to mvc controller

I am trying to pass a folder path to a download controller using #Html.ActionLink, but I am getting could not find the location error like
Could not find file 'C:\Teerth
Content\Project\Colege\WebApp\Media\#item.Content'
However when I give the hard coded value it does work. May I have suggestions what is wrong with that.
Here is my code:
Action method:
public FileResult Download(string fileName, string filePath)
{
byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
string documentName = fileName;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, documentName);
}
view
#Html.ActionLink("Download", "Download", "Marketing", routeValues: new
{
fileName = #item.Content,
filePath = Server.MapPath("~/Media/#item.Content"),
area = "AffiliateAdmin"
}, htmlAttributes: null)
Like mentioned in comments, you've got an error in your view:
The code ("~/Media/#item.Content") renders as C:\Teerth Content\Project\Colege\WebApp\Media\#item.Content, where you actually want Server.MapPath("~/Media/" + #item.Content) to find the actual filename.
But you need to reconsider this design, as it opens up your entire machine to the web. Someone is bound to try Download("C:\Teerth Content\Project\Colege\WebApp\web.config", "web.config"), exposing your connection strings and other application settings, not to mention other files on your server you really don't want clients to download.

How to check whether username already exists using ajax in asp.net?

I am working on an application which has a registration form and I have to display to the user whether the username exists or not.
I am using asp.net mvc3 and planned to use AJAX to achieve this.
I have a form
<tr>
<td>User Name*</td>
<td><input id="UserName" name="UserName" type="text" onblur="check(this.value);"/></td>
<td id= "UName"></td>
</tr>
which calls a .js file that has the folling contents
function check(User) {
...
var url = "/UserNameCheck/Index";
url += "?User=" + User;
xmlHttp.onreadystatechange = state_Change;
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
function state_Change() {
if (xmlhttp.readyState == 4) {// 4 = "Response loaded"
if (xmlhttp.status == 200) {// 200 = Response Error Free
document.getElementById("UName").innerHTML = xmlHttp.responseText
}
else {
alert("Problem retrieving XML data");
}
}
}
I alerted the username and I am getting the correct value that i had entered. Now, the URL is /UserNameCheck/Index where UserNameCheck is a controller and Index is a method in that.
The controller has this code.
public ActionResult Index(string User)
{
string UserName;
try
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
UserName = Request.QueryString["User"];
ConnectionPackage.ConnectionClass cc = new ConnectionPackage.ConnectionClass();
conn = cc.con;
string sql = "Select UserName FROM UserDetails where UserName = '" + UserName + "'";
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.CommandType = CommandType.Text;
object p = cmd.ExecuteScalar();
cmd.ExecuteNonQuery();
string u = (string)p;
if (u.Length==0 || u.Equals("NULL") || u.Equals("null")||u.Equals("Null"))
{
return View();
}
return null;
}
catch (Exception ex){
}
and the view has
String buffer = " <table><tr><td id = 'UName' >" This user name already exists. Please select some other unser name.
buffer = buffer + "</td></tr></table>";
response.getWriter().println(buffer);
I also tried writing
Response.Clear();
Response.Write("UserName already exists. Please select another UserName");
Response.End();
instead of returning View.
But in both the cases, I didn't get any message that the username exists even though I typed a user name that was already present in the database.
The connection string work for inserting into the database, so I dont think there is a problem with that. Is there a problem with the URL that I have mentioned in the js file? Or is my entire approach wrong?
I am basically from java background so dont know much about asp.net. Please do help.
Thank you very much in advance.
I followed what was given in MSDN article How to: Implement Remote Validation in ASP.NET MVC
jQuery in Action is the most popular jQuery book
You're doing alright but you could make this a whole lot easier on yourself. If you are usinng MVC3 with Razor, your app already has jQuery installed.
Use the $.ajax() method to perform the calls to your controller action that checks names...
Bind the $.ajax() call "unobtrusively" which means instead of on your HTML control, bind the event to your control from the jquery/javascript.
Second, if you want a little fancy performance, you can bind it via the live() jquery function or keyup event, so that as you are typing the ajax call is made and you find out realtime.
Ultimately you will end up with a lot less javascript, and your JS stuff will be cleanly separated from your markup.
As far as your controller action is going, it looks fine for playing around and learning, but you'd want to think about either (a) putting your SQL statement as a stored procedure on the db server and calling that, or (b) writing a repository pattern class and then using LINQ to do your query work after the DB fetch.
Another possibility would be to use Entity Framework 4.1 via NuGet to eliminate both needs. It can have a bit of a learning curve, but there's lots of good stuff out there and your example would be fairly simple to get started with.
Let me know if you have any specific concerns with your code and I can provide a more detailed answer.

How to display validation errors on a page with multiple forms in ASP.NET MVC

I have a top-level page called ReceiveItem. Within that page, I have a couple different FORMs - only one of which will be filled out and submitted (depending upon how that item is received). This all works quite well from the UI perspective. Here is the general page structure:
<ReceiveItem.aspx>
<ReceiveNewInventory.ascx>
<ReceiveOrderReturn.ascx>
<ReceiveFromLoan.ascx>
Except, I do not know how to properly display validation errors. Here is my controller for one of those forms:
public ActionResult ReceiveNewInventory(
int id,
int vendorId,
int quantity,
decimal cost) {
var db = new Data();
var item = db.ItemSet.First(i => i.Id == id);
var vendor = db.BusinessSet.First(i => i.Id == vendorId);
ValidateCost(cost);
ValidateQuantity(quantity);
if (ModelState.IsValid) {
item.AddNewInventory(vendor, quantity, cost);
TempData["Message"] = "Added " + quantity +
" inventory items to " + item.FullDisplayName;
return RedirectToAction("Index");
}
else {
TempData["Quantity"] = quantity;
TempData["VendorId"] = vendorId;
TempData["Cost"] = cost;
return RedirectToAction("ReceiveItem", new { id });
}
}
I would like to display the model errors that the two validation functions add using the simple Html.ValidationSummary function; but, those errors seem to get lost because I do the RedirectToAction. (My ReceiveNewInventory controller action does not have a view directly associated with it.)
With the one condition that I still want 1 page with multiple FORMs, what can I change about this design so that my validation messages show up on the ReceiveItem page?
You need to put the ModelState into TempData and extract it in your ReceiveItem action method. Alternatively, change the Redirect to a return View()
hth
Dan
Look at NerdDinner and see how they do it. Very neat and you can display a summary at the top of the page as well as text next to each item if you wish.
let me know if you have trouble and I'll post code.
Why do you redirect to ReceiveItem even if you have errors? When you display the validation message, don't you want the user to have the opportunity to fix their mistakes? If so, why not keep them on the RecevieNewInventory page again and return the view?

Resources