How to convert byte to file asp.net MVC - asp.net-mvc

I want to download the file that I uploaded in the database. The file stored in the byte array. I have created the getDataStudent function and it is working well.
My controller is below.
public class Student: Controller
{
private StudentViewModel getDataStudent(StudentViewModel model)
{
var students = db.students.ToList();
var documents = documentRepo.GetList_Documents();
var queryJoin1 =
from student in students
from document in documents.Where(w => student .UniqueNumber == w.UniqueNumber).DefaultIfEmpty()
select new StudentDto
{
ID = student.ID,
Name = student.Name,
File = document?.DetailFile ?? null, //file to download
};
IEnumerable <StudentDto> studentss= null;
studentss = queryJoin1;
return studentss;
}
public ActionResult Index(StudentViewModel model)
{
studentViewModel = getDataStudent(model);
return View(studentViewModel );
}
[HttpPost]
public FileResult DownloadFile()
{
//code
}
}
and my view is below
#model Student.Data.ViewModels.StudentViewModel
#using (Html.BeginForm())
{
<table class="table">
<tr>
<th>Name</th>
<th>File</th>
</tr>
#foreach (Student.Data.ViewModels.StudentViewModel item in Model)
{
<tr>
<td>#Html.DisplayFor(modelitem => item.Name)</td>
<td> #Html.DisplayFor(modelitem => item.File)</td>
</tr>
}
</table>
}
File Result is still empty, I confused using FileResult.
can you guys tell me how to download files using FileResult on the controller, using the getDataStudent function that I created.
I have never made a file download function before. please help:)

You can implement like this:
public FileStreamResult DownloadFile()
{
// get your students here
var students = ...
string name = "yourname.txt";
FileInfo info = new FileInfo(name);
if (!info.Exists)
{
using (StreamWriter writer = info.CreateText())
{
foreach(var item in students){
writer.WriteLine("{0} {1}", item.ID, item.Name);
}
}
}
return File(info.OpenRead(), "text/plain");
}

Related

Display Active Directory Group in a MVC view

I Am trying to display active directory group member in the view. When i run the Code I am having the error "The model item passed into the dictionary is of type 'System.String[]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[SSSFT.LogIT.Models.ActiveDirectory]'". Debbuging the code show all the group member i am looking for
Model Class
public class ActiveDirectory
{
public int id { get; set; }
//public string Username { get; set; }
//public string Email { get; set; }
public string SamAccountName { get; set; }
}
Controller
public ActionResult Index(string username)
{
username = "sssftappdev";
string[]output = null;
using (var ctx = new PrincipalContext(ContextType.Domain))
using (var user = UserPrincipal.FindByIdentity(ctx, username))
{
if (user != null)
{
output = user.GetGroups() //this returns a collection of principal objects
.Select(x => x.SamAccountName) // select the name. you may change this to choose the display name or whatever you want
.ToArray(); // convert to string array
}
}
return View(output);
}
View
#model IEnumerable<SSSFT.LogIT.Models.ActiveDirectory>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.SamAccountName)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.SamAccountName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.id }) |
#Html.ActionLink("Details", "Details", new { id=item.id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.id })
</td>
</tr>
}
</table>
You can fix this error by simply updating your #model with:
#model String[]
You are currently passing a String[] to your view while expecting an IEnumerable of SSSFT.LogIT.Models.ActiveDirectory. Either update your code to return the right type of data, or adapt your strongly typed view with the actual result you return.

How can i bind a nested list to view with groupby() MVC 4

I have a list of model like this
public class Group
{
public string Name { get; set; }
public string GroupID { get; set; }
}
In controller:
public ActionResult Index()
{
return View(ListGroup);
}
[HttpPost]
public ActionResult Index(List<Group> listModel) {
#ViewBag.Success = "Update Suceess";
return View(listModel);
}
[HttpPost]
public ActionResult Search(Group ModelSearch) {
List<Group> listResult = ListGroup.Where(m=>m.GroupID == ModelSearch.GroupID).ToList();
if (ModelSearch.GroupID == null) return View("Index", ListGroup);
return View("Index", listResult);
}
In view i group the list as below:
#foreach (var items in Model.GroupBy(m => m.GroupID).Select(g => g.ToList()))
{
<tr>
<td colspan="2">#items.ElementAt(0).GroupID</td>
</tr>
foreach (var item in items)
{
<tr>
<td>#Html.TextBoxFor(m => item.GroupID)</td>
<td>#Html.TextBoxFor(m => item.Name)</td>
</tr>
}
}
It can display as groups well but i cannot get value back to controller after button submit was fired.
How can i bind model to view that controller can understand and receive data from view.
according to my understanding,
you need to use a for loop rather than a foreach this will index your collections, by doing this modelbinder will work.
#for(var i = 0; i < items; i++)
{
<tr>
<td>#Html.TextBoxFor(m => m[i].GroupID)</td>
<td>#Html.TextBoxFor(m => m[i].Name)</td>
</tr>
}

MVC Binding views to controllers

Model
public class ImportFiles
{
public string FileName;
public bool FileSelected { get; set; }
}
Controller
(Trying to get files from a particular folder) File names are coming , both contain the word "employee" Then I am searching for a string , in the file name and taking some actions.
[HttpGet]
public ActionResult ImportFiles()
{
string folderpath = #"C:\Users\uvaish\Documents\Visual Studio 2010\Projects\MVCDemo\MVCDemo\Models";
string filename = "*";
string[] fileList = System.IO.Directory.GetFiles(folderpath, filename);//getting the file names from the folder as an array
List<ImportFiles> inputFiles = new List<ImportFiles>(fileList.Length);//making a list of same number of elements as the number of files
foreach (string str in fileList)
{
ImportFiles inputFile = new ImportFiles();
inputFile.FileName = Path.GetFileName(str);
inputFile.FileSelected = false;
inputFiles.Add(inputFile);
}
return View(inputFiles);
}
[HttpPost]
public string ImportFiles(List<ImportFiles> import)
{
foreach (ImportFiles importFile in import)
{
if (importFile.FileSelected == true)
{
if (importFile.FileName.Contains("ployee"))//Getting a null point reference here
{
return ("file found");
}
else
{
return ("no file found");
}
}
else
{
return ("no file selected");
}
}
return ("done");
}
View
#model IList<ProjectName.Model.ImportFiles>
#using AetnaCoventryMigration.Model;
#using (Html.BeginForm("ImportFiles", "Admin", FormMethod.Post))
{
<div class="panel panel-default">
<table width="550px" class="mGrid table">
<tr>
<th>
Select
</th>
<th>
File Name
</th>
</tr>
#for (var i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Html.EditorFor(x => x[i].FileSelected)
</td>
<td>
#Model[i].FileName
</td>
</tr>
}
</table>
In this program , I am trying to access the checkboxes as well as the file names for each object passed in the view. I am able to access the checkbox and know whether it is true or false ( checked or unchecked ) but I'm not able to access the file names.
Change
<td>
#Model[i].FileName
</td>
To :
#Html.DisplayFor(x => x[i].FileName)
or add
#Html.HiddenFor(x => x[i].FileName)
it is necessary to generate a field for the correct data binding

Reading and Displaying Uploaded text Files in MVC

Is it possible to read uploaded text files e.g .txt and display the content in a textbox ? I want to do a file conversion of the uploaded files. I've managed to upload and validate the files I would like at the click of a button to read the contents and display them in a textbox ready for conversion. How would I go about doing this?
Upload class
public class UploadedFile
{
public long Size { get; set; }
public string Path { get; set; }
public string Name { get; set; }
// public int Length { get; set; }
public string extension { get; set; }
}
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
var supportedTypes = new[] { "txt", "rtf", "html", "xaml", "xslx" ,"pdf", "doc", "docx", "csv" };
var fileExt = System.IO.Path.GetExtension(file.FileName).Substring(1);
if (!supportedTypes.Contains(fileExt))
{
ModelState.AddModelError("file", "Invalid type. Only the following types (txt, rtf, html, xslx, pdf, xaml, doc, docx, csv) are supported.");
return View();
}
if (file.ContentLength > 200000)
{
ModelState.AddModelError("file", "The size of the file should not exceed 200 KB");
return View();
}
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/uploads"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
public ActionResult About()
{
var uploadedFiles = new List<UploadedFile>();
var files = Directory.GetFiles(Server.MapPath("~/uploads"));
foreach(var file in files)
{
var fileInfo = new FileInfo(file);
var uploadedFile = new UploadedFile() {Name = Path.GetFileName(file)};
uploadedFile.Size = fileInfo.Length;
uploadedFile.extension = Path.GetExtension(file);
uploadedFile.Path = ("~/uploads/") + Path.GetFileName(file);
uploadedFiles.Add(uploadedFile);
}
return View(uploadedFiles);
}
}
So far the files uploaded are listed in a table.I would like to read and display the contents if the button is Clicked and the contents placed inside the text area below the table. So I can perform conversion.
How would I achieve this? Thanks
`<script>$('btnreadfile').click(function () {
document.location = '#Url.Action("ReadTextFile","Home")'; });</script>
<input id="btnreadfile" name="btnReadFile" type="submit" value="Read File"/>
`My button Code
Working code. Fully tested
in you _Layout.cshtml
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
</head>
in your About.cshtml
Table mark up
<table style="background-color: lightgreen; border: solid 2px black;">
<tr>
<td>
<b>Name</b>
</td>
<td>
<b>Size</b>
</td>
<td>
<b>Preview</b>
</td>
<td>
<b>Read File</b>
</td>
</tr>
#foreach (var file in Model)
{
<tr>
<td>
#file.Name
</td>
<td>
#(file.Size / 1000) KB
</td>
<td>
#(file.extension)
</td>
<td>
<input id="btnreadfile" name="#file.Name" class='btnClick' type="button" value="Read File"/>
<textarea rows="4" cols="50">
</textarea>
</td>
</tr>
}
</table>
in your About.cshtml all the way bottom add this script
<script>
$.ajax({
url: "/Home/ReadTextFile",
type: "GET",
data: { fileName: $(this).attr("name") },
DataType: "text",
success: function (str) {
alert(str);
$("textarea").val(str); // this line has to be replaced with more dynamic jQuery selector that can select this button next textarea
//$(this).next("textarea").val(str);
},
error: function (err) {
alert(err);
}
});
});
</script>
in Your Controller
Add reference using System.Runtime.InteropServices.ComTypes;
add a JsonResult Method
public JsonResult ReadTextFile(string fileName)
{
string retString = string.Empty;
string path = Path.Combine(Server.MapPath("~/uploads") , fileName );
if (System.IO.File.Exists(path))
{
if (Path.GetExtension(path) == "doc" || Path.GetExtension(path) == ".docx")
{
Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
object miss = System.Reflection.Missing.Value;
object readOnly = true;
object wordPath = path;
Microsoft.Office.Interop.Word.Document docs = word.Documents.Open(
ref wordPath,
ref miss,
ref readOnly,
ref miss, ref miss, ref miss,
ref miss, ref miss, ref miss,
ref miss, ref miss, ref miss,
ref miss, ref miss, ref miss, ref miss);
for (int i = 0; i < docs.Paragraphs.Count; i++)
{
retString += " \r\n " + docs.Paragraphs[i + 1].Range.Text.ToString();
}
}
else if (Path.GetExtension(path) == "txt")
{
using (StreamReader sr = new StreamReader(path))
{
retString = sr.ReadToEnd();
}
}
}
return Json(retString, JsonRequestBehavior.AllowGet);
}
Note: I have considered to read only files with extension .doc, .docx and .txt any other extensions should be handled further

#Html.DisplayName is not displaying EmailAddress Properly

I am trying to display like this
var value = "Kartheek#gmail.com"
#Html.DisplayName(value)
Result is : com only.
why? what have to use in this case
here i am explaining more
My intention is to display content in very generic with grid.
public class Grid
{
private Type type { get; set; }
public Grid(IEnumerable datasource)
{
if (datasource == null)
{
throw new ArgumentNullException("datasource");
}
this.type = datasource.GetType().GetGenericArguments().Single();
this.Data = datasource;
}
public IEnumerable Data { get; set; }
public IEnumerable<System.Reflection.PropertyInfo> Props
{
get
{
return this.type.GetProperties().AsEnumerable();
}
}
}
This is my c# class for grid. i am assigning values in to Grid.data and with viewbag i am sending grid data to view and then i am using this with in partial view
here my partial view code
#if (Model != null)
{
<table style="width: 100%">
<thead>
<tr>
#foreach (var col in Model.Props)
{
<th>#Html.Label(col.Name)</th>
}
</tr>
</thead>
<tbody>
#foreach (var item in Model.Data)
{
<tr>
#foreach (var prop in Model.Props)
{
var val = prop.GetValue(item, null).ToString();
<td>#Html.DisplayName(val)</td>
}
</tr>
}
</tbody>
</table>
}
Finally i got answer with this.. But i am not satisfied with that bcz there is another good solution for it.
var val = "kartheek#gmail.com";
<span>#val</span>

Resources