convert string to array in mvc 4 - asp.net-mvc-4

In my recent mvc 4 project, I store multiple image and other files (such as doc, pdf, ppt etc.) as string in my database. Now I want to show this multiple image and want to show link of other files.
For example, I store data as string in my db as like as given below:
1980082_10201802177236118_516383197_o.jpg, ASP.NET MVC Interview Questions & Answers.pdf, Sample-1.jpg,
Now I want to fetch this string and show image and give the link of the other files.

I hope it will help.First when you save in your database you have to make sure you save it with all the paths, not only the filenames. In simple In your Action:
public FilePathResult GetDoc(int yourParam)
{
var path= (from r in yourContext.yourTable where id == yourParam
select r.path).FirstOrDefault()
//Considering that your path contains also the folder
return new FilePathResult(path);
}
In your View:
<img src="#Url.Action("GetDoc", "YourController", new { yourParam=Model.yourParam}) " />
#*For a link*#
<a href="#Url.Action("GetDoc", "YourController", new { yourParam=Model.yourParam}) ">#Model.TheNameOfYourFile <a/>

Firstly note that, it is not good idea to store that file names in one row in db. If I understood you right, to extract images and files from that rows, create a model that contains list of different file list:
public class RowResult
{
public RowResult()
{
Images = new List<string>();
Pdfs = new List<string>();
}
public List<string> Images { get; set; }
public List<string> Pdfs { get; set; }
//you can add other file types here
}
Create a method that return result for every row:
public RowResult ExtractFilesFromRow(string row)
{
RowResult result = new RowResult();
string[] parts = row.Split(' ');
foreach (string part in parts)
{
if (part.TrimEnd(',').EndsWith(".jpeg")) result.Images.Add(part);
if (part.TrimEnd(',').EndsWith(".pdf")) result.Pdfs.Add(part);
//add others here..
}
return result;
}
And finally, to show them in view for each row you can get RowResult in db and fill List<RowResult>. In Action:
....
List<RowResult> list = new List<RowResult>();
foreach (string row in rows)
{
list.Add(ExtractFilesFromRow(row));
}
...
return list;
In view:
#foreach (string result in Model)
{
//here depends on you want
<img src="#Url.Content("~/Uploads/Images/" + result.Images[0])" />
....
<img src="#Url.Content("~/Uploads/Images/" + result.Images[1])" />
}

I store multiple image and other files (such as doc, pdf, ppt etc.) as string in my database
I assume you mean you save the file names as string in your database.
Now let's start with the db data you shared
For example, I store data as string in my db as like as given below:
1980082_10201802177236118_516383197_o.jpg, ASP.NET MVC Interview Questions & Answers.pdf, Sample-1.jpg,
when comma seperated becomes this
1980082_10201802177236118_516383197_o.jpg
ASP.NET MVC Interview Questions & Answers.pdf
Sample-1.jpg
Now what we have here is only filenames and to "physical path" to where these files are stored.
So for this to work you WILL have to save the file path in the database too. Unless you have defined a path say "C:/SomeApp/MyDump/" and you are simply dumping all the files here.
In case you are then you can use that path append it with the file name and show on the UI. The file extension could help you decide what HTML to use (<img> or <a> to display image or show a download link)

Related

Easy way to retrieve image source in abp

I'm pretty new to ABP Framework and probably this question has a really simple answer, but I haven't managed to find it. Images are an important part of any app and handling them the best way (size, caching) is mandatory.
Scenario
setup a File System Blob Storing provider. This means that the upload file will be stored in the file system as an image file
make a service that uses a Blob container to save and retrieve the image. So, after saving it, I use the unique file name as a blob name. This name is used to retrieve it back.
the user is logged in, so authorization is required
I can easily obtain the byte[]s of the image by calling blobContainer.GetAllBytesOrNullAsync(blobName)
I want to easily display the image in <img> or in datatable row directly.
So, here is my question: is there an easy way to use a blob stored image as src of a <img> directly in a razor page? What I've managed to achieve is setting in the model, a source as a string made from image type + bytes converted to base 64 string (as here) however in this case I need to do it in the model and also I don't know if caching is used by the browser. I don't see how caching would work in this case.
I am aware that this may be a question more related to asp.net core, but I was thinking that maybe in abp there is some way via a link to access the image.
If you have the ID of the blob then it is easy to do. Just create a Endpoint to get the Image based on the blob id.
Here is the sample AppService
public class DocumentAppService : FileUploadAppService
{
private readonly IBlobContainer<DocumentContainer> _blobContainer;
private readonly IRepository<Document, Guid> _repository;
public DocumentAppService(IRepository<Document, Guid> repository, IBlobContainer<DocumentContainer> blobContainer)
{
_repository = repository;
_blobContainer = blobContainer;
}
public async Task<List<DocumentDto>> Upload([FromForm] List<IFormFile> files)
{
var output = new List<DocumentDto>();
foreach (var file in files)
{
using var memoryStream = new MemoryStream();
await file.CopyToAsync(memoryStream).ConfigureAwait(false);
var id = Guid.NewGuid();
var newFile = new Document(id, file.Length, file.ContentType, CurrentTenant.Id);
var created = await _repository.InsertAsync(newFile);
await _blobContainer.SaveAsync(id.ToString(), memoryStream.ToArray()).ConfigureAwait(false);
output.Add(ObjectMapper.Map<Document, DocumentDto>(newFile));
}
return output;
}
public async Task<FileResult> Get(Guid id)
{
var currentFile = _repository.FirstOrDefault(x => x.Id == id);
if (currentFile != null)
{
var myfile = await _blobContainer.GetAllBytesOrNullAsync(id.ToString());
return new FileContentResult(myfile, currentFile.MimeType);
}
throw new FileNotFoundException();
}
}
Upload function will upload the files and Get function will get the file.
Now set the Get route as a src for the image.
Here is the blog post: https://blog.antosubash.com/posts/dotnet-file-upload-with-abp
Repo: https://github.com/antosubash/FileUpload

How to generate a single PDF using Rotativa from a View which has different dynamic headers in ASP.Net MVC?

I am using Rotativa to generate a single PDF file for single invoice, in Asp.Net MVC application. I am using the command --header-html with CustomSwitches of ViewAsPdf to include header for each page of an Invoice as follows,
public ActionResult GenerateSingleInvoicePDF(string invoiceId)
{
var invoiceViewModel = new InvoicePDFModel();
... // get content from database;
...
...
ViewBag.InvoiceDetail = invoiceViewModel;
string customSwitches = string.Format("--print-media-type --allow {0} --header-html {0} --page-offset \"0\" --header-spacing \"1\" ", Url.Action("InvoiceHeader", "Order", new { invNumber =
invoiceViewModel.invNo, invDate = invoiceViewModel.InvoiceDateString, shippAddr = invoiceViewModel.DeliveryAddr, billingAddress = invoiceViewModel.BillingAddr }, "http"));
return new ViewAsPdf("~/SingleInvoiceView.cshtml")
{
FileName = "SingleInvoice.pdf",
PageSize = Size.A4,
CustomSwitches = customSwitches
};
}
This works perfectly without any issue. Now my need is how to generate a single PDF for multiple invoice. I tried the above code for multiple invoice as follows,
public ActionResult GenerateMultipleInvoicePDF(string invoiceIds)
{
var invoiceList = new List<InvoicePDFModel>
... // get list of content from database;
...
...
ViewBag.InvoiceList = invoiceList;
string customSwitches = // don't know how to define header view for multiple invoice.
return new ViewAsPdf("~/MultiInvoiceView.cshtml")
{
FileName = "MultiInvoice.pdf",
PageSize = Size.A4,
CustomSwitches = customSwitches
};
}
But I am stuck at the header part. Because, header content varies for each invoice. Any suggestions how to do this?
For your specific case, taking a look at your individual invoice code
Url.Action("InvoiceHeader", "Order", new { invNumber =
invoiceViewModel.invNo, invDate = invoiceViewModel.InvoiceDateString, shippAddr = invoiceViewModel.DeliveryAddr, billingAddress = invoiceViewModel.BillingAddr }, "http")
Maybe it would be a good idea to take all the parameters you are sending to the view and store them inside a model. This model could keep a list or collection of classes or models, each of them with the same pack of parameters that you send for an individual invoice. Then, on the view, you might be able to determine, depending on your requirements, which parameters you must specify for each page.
Bearing in mind that Rotativa uses WkHtmlToPdf, and as you can chek in this, an other posts, the oficial documentation sets that the page number, among other parameters, is send to the header/footer.
Could be tricky, but this means you might be able to achieve what you are looking for, following these steps:
Generate MVC action and asociated view, to generate the header, accepting the model you wish.
Inside the view, access QueryString parameter for page number, so this way you can identify which invoice you are printing (supossing that each invoice prints no more and no less than one page).
Using the collection of classes from your model, access by index the particular invoice that matches the page number from the previous step, and write the view according to the parameters that apply for the current invoice.

When database is not available what is the best way to store the value

I have an API which is accepting the data which will be used by multiple users. I don't have a Database available what is the best approach to do so.
Asp.net core project
In my opinion, you can use Files. Data will write in files, or you can Cookies, LocalStorage to store data.
You can save your data to a file,I think it will be more flexible and you can directly edit the file
content to modify your data, check my demo to save and get data from file to a list in web api
project:
[Route("/save")]
public async Task SaveAsync()
{
string[] lines = { "First line", "Second line", "Third line" };
using StreamWriter file = new StreamWriter("SaveData.txt");
foreach (string line in lines)
{
await file.WriteLineAsync(line);
}
}
[Route("/getfile")]
public async Task testAsync()
{
string[] lines = System.IO.File.ReadAllLines(#"C:\****\SaveData.txt");
List<string> mylist =new List<string>();
System.Console.WriteLine("Contents of WriteLines2.txt = ");
foreach (string line in lines)
{
mylist.Add(line);
}
}
And this is the official tutorial:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/file-system/how-to-write-to-a-text-file
Result:

How to save data into application vb.net ? (Not use database or txt file)

I a newbie in VB.net. I have a small project that save data from textbox. (just simple: create textbox, fill my name to textbox and save it).
But I don't want use database or txtfile because if I use like that, I will have 2 file: my app.exe and database file. I don't know whether there have anyway to save data into this my app.exe. Just have 1 file app.exe, database is included in this app (App is same to excel file: just have 1 file excel which can fill data and save)
Obviously you have a class Student (from your comment)
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
For binding to DataGridView you can use BindingList<Student>.
Then when you close your application save in JSON format.
var data = _yourBindingList.ToList();
var serializedData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
System.IO.File.WriteAllText(#"fileName.anyExtensionYouWant", serializedData);
When application starts load data from the file and deserialize it.
var data = System.IO.File.ReadAllText(#"fileName.anyExtensionYouWant", serializedData);
var loadedStudents = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Student>>(data);
_yourBindingList = new BindingList(loadedStudents);
yourDataGridView.DataSource = _yourBindingList;
The easy way is to save the text to a txt file
My.Computer.FileSystem.WriteAllText
https://msdn.microsoft.com/es-es/library/27t17sxs(v=vs.90).aspx
So
My.Computer.FileSystem.WriteAllText("C:\TestFolder1\test.txt", "This is new text to be added.", False)
on your're case can be
My.Computer.FileSystem.WriteAllText("C:\TestFolder1\test.txt", textbox1.text, False)
If you need to use MyDocuments or Desktop folders you need to use relative system routes

Variable number of HttpPostedFileBase objects

Currently, I have this:
public ActionResult Add(FormCollection form, HttpPostedFileBase fr, HttpPostedFileBase en, HttpPostedFileBase es)
{
Upload(fr, "fr");
Upload(en, "en");
Upload(es, "es");
...
}
This works for what we're doing currently, but just learned of a new requirement where the system needs the ability to add other languages. This is the only part where I have an issue.
I tried:
public ActionResult Add(FormCollection form, HttpPostedFileBase[] fr)
{
foreach(var file in fr)
{
Upload(file, "I'mStuck");
}
...
}
as a test, but it will only have 1 element and it is the one where id/name = fr. Makes sense, but not particularly helpful for what I need.
I could do:
for (string file in Request.Files)
{
...
}
which would handle the upload component fine, but the issue is that unless I can force them to standardize against a whatever_langabbreviation.extension file format, which I can't, I'm not going to be able to know what the language abbreviation is.
How can I obtain the id/name fields for the input type=file objects within the controller?
I was actually incorrect. The string returned is actually the id or name (think name, but considering I typically pair id/name, it works).
For the controller that renders the view initially, I did:
List<Languages> langs = db.Languages.ToList();
viewmodel.Languages = langs;
return View(viewmodel);
In the view itself:
foreach(Language lang in Model.Languages)
{
// Label
<input type="file" id="#lang.Abbreviation" name="#lang.Abbreviation" />
}
And in the post event:
foreach(string file in Request.Files)
{
HttpPostedFileBase fb = Request.Files[file];
Upload(fb, file);
}
And it handles as it is supposed to (Upload being a function that just adds a new item to another table.