Passing MP3 from controller to view .NET CORE MVC - c#

I am trying to pass a FileContentResult from my controller that has a byte[] MP3 file into the view,
my problem is when I do that(return a file to view) the view renders a new HTML page with an audio player.
I want to have a player on my Html page waiting for an audio file from the controller, maybe as a model? not sure.
any help is appreciated!
[Route("morse")]
public FileResult Morse(string msg)
{
_decoder.MorseBuilder(msg, out byte[] audio, out TimeSpan time);
return File(audio, "audio/mpeg"); //byte[]
}
currently my view (Index.cshtml) is empty.
this is what I ended up doing:

You could use Url.Action() method to call the action method and load MP3 file, please refer to the following sample code:
public class AppFile
{
[Key]
public int FileID { get; set; }
public string FileName { get; set; }
public byte[] Content { get; set; }
public string ContentType { get; set; }
}
Controller:
public IActionResult FileIndex()
{
return View(_context.AppFiles.ToList());
}
[HttpGet]
public ActionResult GetVnAudioStream(int id)
{
if (id > 0)
{
var pronunciation = _context.AppFiles.Where(c=>c.FileID == id).FirstOrDefault().Content;
if (pronunciation != null && pronunciation.Length > 0)
{
return File(pronunciation, "audio/mp3");
}
}
return null;
}
View Page:
#model IEnumerable<netcore5.Models.AppFile>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.FileID)
</th>
<th>
#Html.DisplayNameFor(model => model.FileName)
</th>
<th>
#Html.DisplayNameFor(model => model.Content)
</th>
<th>
#Html.DisplayNameFor(model => model.ContentType)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FileID)
</td>
<td>
#Html.DisplayFor(modelItem => item.FileName)
</td>
<td>
<audio controls>
<source src='#Url.Action("GetVnAudioStream","Home", new {id = item.FileID})' type='audio/mp3' />
</audio>
</td>
<td>
#Html.DisplayFor(modelItem => item.ContentType)
</td>
</tr>
}
</tbody>
</table>
The result like this:

Related

How to update multiple rows at once from the View (ASP.NET - Core)

I've got a View which shows a table of Devices that are stored in my Database, the database is made using Code-First with Entity Framework Core. Now my goal is to update the EnableAlertsUpload boolean of multiple rows at the same time. As can be seen in the picture below.
Now when I run the code and press the update button the page will just refresh without updating the EnableAlertsUpload boolean. Any help on this would be greatly appreciated, most explanations only tell ho to update a single value by ID but not multiple rows at the same time.
My code looks as follows:
Controller
public async Task<IActionResult> EditList()
{
var devices = db.Devices;
return View(devices);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditList(int id, [Bind("EnableAlertsUpload")] Devices[] devices)
{
if (ModelState.IsValid)
{
try
{
foreach (Devices dev in devices)
{
db.Update(dev);
}
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
return NotFound();
}
return RedirectToAction(nameof(IndexV2));
}
return View(devices);
}
EditList View
#model IEnumerable<FrontlineAI.Models.Devices>
<h1>Devices</h1>
<form asp-action="EditList">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.objid)
</th>
<th>
#Html.DisplayNameFor(model => model.device)
</th>
<th>
#Html.DisplayNameFor(model => model.group)
</th>
<th>
#Html.DisplayNameFor(model => model.host)
</th>
<th>
#Html.DisplayNameFor(model => model.EnableAlertsUpload)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.objid)
</td>
<td>
#Html.DisplayFor(modelItem => item.device)
</td>
<td>
#Html.DisplayFor(modelItem => item.group)
</td>
<td>
#Html.DisplayFor(modelItem => item.host)
</td>
<td>
<td>#Html.CheckBoxFor(modelItem => item.EnableAlertsUpload)</td>
</td>
</tr>
}
</tbody>
</table>
<button input type="submit" value="Edit">Update</button>
</form>
Devices Model
public partial class Devices
{
[Key()]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int objid { get; set; }
public string group { get; set; }
public string device { get; set; }
public string host { get; set; }
public bool EnableAlertsUpload { get; set; }
}
It seems that you you did not successfully bind the data, you can try my following code.
EditList View
#model IEnumerable<Devices>
#{
ViewData["Title"] = "Edit";
}
<h1>Devices</h1>
<form asp-action="EditList">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.objid)
</th>
<th>
#Html.DisplayNameFor(model => model.device)
</th>
<th>
#Html.DisplayNameFor(model => model.group)
</th>
<th>
#Html.DisplayNameFor(model => model.host)
</th>
<th>
#Html.DisplayNameFor(model => model.EnableAlertsUpload)
</th>
<th></th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.HiddenFor(m => m.ToList()[i].objid)
#Html.DisplayFor(m => m.ToList()[i].objid)
</td>
<td>
#Html.HiddenFor(m => m.ToList()[i].device)
#Html.DisplayFor(m => m.ToList()[i].device)
</td>
<td>
#Html.HiddenFor(m => m.ToList()[i].group)
#Html.DisplayFor(m => m.ToList()[i].group)
</td>
<td>
#Html.HiddenFor(m => m.ToList()[i].host)
#Html.DisplayFor(m => m.ToList()[i].host)
</td>
<td>#Html.CheckBoxFor(m => m.ToList()[i].EnableAlertsUpload)</td>
</tr>
}
</tbody>
</table>
<button input type="submit" value="Edit">Update</button>
</form>
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditList(int id, List<Devices> devices)
{
if (ModelState.IsValid)
{
try
{
foreach (Devices dev in devices)
{
_context.Update(dev);
}
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
return NotFound();
}
}
return RedirectToAction(nameof(EditList));
}
Result

How to display all rows with same ID in ASP.NET MVC?

My Index page displays all rows from an Azure SQL Database. When I click a row I get redirected to a unique URL with a QR code for that URL and it also displays the data for only that row. Each row has it's own unique ID, but also a truckID. The truckID is for a driver who can "own" several rows of data, so I want to show every row with the same truckID after a row is clicked.
This is what I've got so far:
MODEL
namespace QR
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("data")]
public partial class data
{
[Required]
[StringLength(50)]
public string Contract { get; set; }
[StringLength(50)]
public string Sort { get; set; }
public int? Report { get; set; }
public double? InputKG { get; set; }
public double? OutputKG { get; set; }
public double? Recovery { get; set; }
public double? Si { get; set; }
public double? Cu { get; set; }
public double? Mn { get; set; }
public double? Mg { get; set; }
public double? Zn { get; set; }
public double? Cr { get; set; }
public double? Fe { get; set; }
public double? Pb { get; set; }
public int? truckID { get; set; }
[Key]
public int ID{ get; set; }
}
}
VIEW (after a row is clicked from Index)
#model QR.data
#{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>QR code</h2>
<img src="/Home/BarcodeImage?barcodeText=#Request.Url.OriginalString"/>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Contract)
</th>
<th>
#Html.DisplayNameFor(model => model.Sort)
</th>
<th>
#Html.DisplayNameFor(model => model.Report)
</th>
<th>
#Html.DisplayNameFor(model => model.InputKG)
</th>
<th>
#Html.DisplayNameFor(model => model.OutputKG)
</th>
<th>
#Html.DisplayNameFor(model => model.Recovery)
</th>
<th>
#Html.DisplayNameFor(model => model.Si)
</th>
<th>
#Html.DisplayNameFor(model => model.Cu)
</th>
<th>
#Html.DisplayNameFor(model => model.Mn)
</th>
<th>
#Html.DisplayNameFor(model => model.Mg)
</th>
<th>
#Html.DisplayNameFor(model => model.Zn)
</th>
<th>
#Html.DisplayNameFor(model => model.Cr)
</th>
<th>
#Html.DisplayNameFor(model => model.Fe)
</th>
<th>
#Html.DisplayNameFor(model => model.Pb)
</th>
</tr>
<tr>
<td>
#Html.DisplayFor(model => model.Contract)
</td>
<td>
#Html.DisplayFor(model => model.Sort)
</td>
<td>
#Html.DisplayFor(model => model.Report)
</td>
<td>
#Html.DisplayFor(model => model.InputKG)
</td>
<td>
#Html.DisplayFor(model => model.OutputKG)
</td>
<td>
#Html.DisplayFor(model => model.Recovery)
</td>
<td>
#Html.DisplayFor(model => model.Si)
</td>
<td>
#Html.DisplayFor(model => model.Cu)
</td>
<td>
#Html.DisplayFor(model => model.Mn)
</td>
<td>
#Html.DisplayFor(model => model.Mg)
</td>
<td>
#Html.DisplayFor(model => model.Zn)
</td>
<td>
#Html.DisplayFor(model => model.Cr)
</td>
<td>
#Html.DisplayFor(model => model.Fe)
</td>
<td>
#Html.DisplayFor(model => model.Pb)
</td>
</tr>
</table>
<p>
#Html.ActionLink("Back to List", "Index")
</p>
CONTROLLER
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
data data= db.data.Find(id);
if (data == null)
{
return HttpNotFound();
}
return View(data);
}
And on the Index I have this link:
#Html.ActionLink("QR", "Details", new { id = item.ID})
Help?
With this answer I presume two things:
db is a DbContext and has a property called data which is a DbSet<data>
You don't have any other models for your data, only the data class
If the above is true, here's what you should do:
In the controller:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
data data = db.data.Find(id);
if (data == null)
{
return HttpNotFound();
}
var groupedData = db.data.Where(d => d.truckID == data.truckID).ToList();
return View(groupedData);
}
In your view (Details)
// This is after declaring the table headers
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(model => item.Contract)
</td>
// Fill in rest of the td rows as you did
<td>
#Html.DisplayFor(model => item.Pb)
</td>
</tr>
}
This should display all of the rows correctly.
Also, this is just for readability, but it is really important, capitalize your class names, i.e. it should be public partial class Data not data.
You didn't get any error on this statement ?
data data= db.data.Find(id);
I think it has to be like this
data data= db.data.Find(i=>i.ID == id);
and I supposed you were using foreach loop to print all of the data and in that loop you have that #Html.ActionLink.

ASP.NET MVC pass an object from table to the controller?

I want to pass a model to the controller after klicking on a row.
this is my code which doesn't work.
<table class="table">
<tr>
<th>
<p>Sender</p>
</th>
<th>
<p>Subject</p>
</th>
<th>
<p>Received</p>
</th>
<th>
<p>HasAttachment</p>
</th>
<th></th>
</tr>
#foreach (var item in Model.Inbox) {
<tr class="mail-row" onclick="location.href = '#(Html.ActionLink ("", "MailViewer", "Profile", new { mail = item }, null ))'">
<td>
#Html.DisplayFor(modelItem => item.Sender)
</td>
<td>
#Html.DisplayFor(modelItem => item.Subject)
</td>
<td>
#Html.DisplayFor(modelItem => item.Received)
</td>
<td>
#Html.DisplayFor(modelItem => item.HasAttachment)
</td>
</tr>
}
</table>
I tried to use Url.Action but i got only the Object Type in the url and not the actual object.
I try to send this object:
public class Mail
{
public string Sender { get; set; }
public string Subject { get; set; }
public DateTime Received { get; set; }
public bool HasAttachment { get; set; }
public string content { get; set; }
}
it is possible with json but you will but you should send id and get the data in action based on that id but with json you can do it like this
My action link will be
#Html.ActionLink("senddata", "MailViewer",new{ #data = Json.Encode(item) } )
and my action will be something like this
public ActionResult MailViewer(string data)
{
var result = System.Web.Helpers.Json.Decode<Mail>(data);
return View();
}

Filtering by parameter & Routing

I have an MachineInfo view page which I am showing 60 different specifications of the related machine like processor info, ram info, disk info, db info etc.
ActionLink to this page is:
#Html.ActionLink("Machine Info", "MachineInfo", new { id = Model.LicenseKey }) |
Controller:
public ActionResult MachineInfo(string LicenseKey)
{
if (LicenseKey == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Farm farm = db.Farms.Find(LicenseKey);
if (farm == null)
{
return HttpNotFound();
}
return View(farm);
}
Farm Model:
public partial class Farm
{
public Farm()
{
this.FarmChanges = new HashSet<FarmChange>();
this.FarmDetails = new HashSet<FarmDetail>();
this.FarmTables = new HashSet<FarmTable>();
}
public int Id { get; set; }
public string LicenseKey { get; set; }
public string Name { get; set; }
public string CustomerName { get; set; }
public virtual ICollection<FarmChange> FarmChanges { get; set; }
public virtual ICollection<FarmDetail> FarmDetails { get; set; }
public virtual ICollection<FarmTable> FarmTables { get; set; }
}
FarmDetails Model:
public partial class FarmDetail
{
public System.Guid Id { get; set; }
public int FarmId { get; set; }
public int Type { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public virtual Farm Farm { get; set; }
}
All the MachineInfo is coming from the "Value" in the FarmDetails table.
View:
#model IEnumerable<FarmManagement.Models.FarmDetail>
#{
ViewBag.Title = "Machine Info";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Machine Info</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Type)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Value)
</th>
<th>
#Html.DisplayNameFor(model => model.Farm.LicenseKey)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Type)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Value)
</td>
<td>
#Html.DisplayFor(modelItem => item.Farm.LicenseKey)
</td>
<td>
</td>
</tr>
}
</table>
#Html.ActionLink("Back to Farms List", "Index")
I am trying to show MachineInfo of a specific machine (LicenseKey=ABXYZ-XYZAB) with this url: mydomain.com/MachineInfo/ABXYZ-XYZAB
I need to filter the view by LicenseKey.
After my all tries, I'm only getting 400 - Bad Request error (Because LicenseKey == null) or getting the MachineInfo of ALL machines, not the specific machine with LicenseKey=ABXYZ-XYZAB.
What I am doing wrong?
Change your actionlink code
#Html.ActionLink("Machine Info", "MachineInfo", new { id = Model.LicenseKey })
to
#Html.ActionLink("Machine Info", "MachineInfo", new { LicenseKey = Model.LicenseKey })
As the Action link parameter name should match with the controller action parameter name.
Solved the problem after making following changes:
New Controller After Change:
public ActionResult MachineInfo(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
FarmDetail farmdetail = db.FarmDetails.Where(x => x.FarmId == id).FirstOrDefault();
if (farmdetail == null)
{
return HttpNotFound();
}
return View(farmdetail);
}
New View After Change:
#model FarmManagement.Models.FarmDetail
#{
ViewBag.Title = "Machine Info";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Machine Info</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Type)
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Value)
</th>
<th>
#Html.DisplayNameFor(model => model.Farm.LicenseKey)
</th>
<th></th>
</tr>
#for (int i = 0; i < Model.Farm.FarmDetails.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.Farm.FarmDetails.ElementAt(i).Type)
</td>
<td>
#Html.DisplayFor(model => model.Farm.FarmDetails.ElementAt(i).Name)
</td>
<td>
#Html.DisplayFor(model => model.Farm.FarmDetails.ElementAt(i).Value)
</td>
<td>
#Html.DisplayFor(model => model.Farm.LicenseKey)
</td>
<td>
</tr>
}
</table>
#Html.ActionLink("Back to Farms List", "Index")
I needed to use a where sentence in Controller;
FarmDetail farmdetail = db.FarmDetails.Where(x => x.FarmId == id).FirstOrDefault();
And removed IEnumerable from the View and changed #foreach to #for with ElementAt(i).
#Html.DisplayFor(model => model.Farm.FarmDetails.ElementAt(i).Name)

Enable boolean and enter text in view then pass back to controller - MVC

I have a view that displays a boolean (currently defaulted to 0) in a box format in the view that I cannot check to activate as true and also want to enter text in the result field to pass back to the controller and save both changes to a table. Can someone please explain what I have to do to allow this functionality to work please.
Controller code
public ActionResult P1A1Mark()
{
List<MarkModel> query = (from row in db.submits
where row.assignment_no.Equals("1") && row.group_no == 1
group row by new { row.assignment_no, row.student_no, row.student.firstname, row.student.surname } into g
select new MarkModel
{
student_no = g.Key.student_no,
student_surname = g.Key.surname,
student_firstname = g.Key.firstname
}
).ToList();
return View(query);
}
View
#model IEnumerable<MvcApplication2.Models.MarkModel>
#{
ViewBag.Title = "P1A1Mark";
}
<h2>Mark Student Assignments</h2>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.student_no)
</th>
<th>
#Html.DisplayNameFor(model => model.student_surname)
</th>
<th>
#Html.DisplayNameFor(model => model.student_firstname)
</th>
<th>
#Html.DisplayNameFor(model => model.submitted)
</th>
<th>
#Html.DisplayNameFor(model => model.result)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.student_no)
</td>
<td>
#Html.DisplayFor(modelItem => item.student_surname)
</td>
<td>
#Html.DisplayFor(modelItem => item.student_firstname)
</td>
<td>
#Html.DisplayFor(modelItem => item.submitted)
</td>
<td>
#Html.DisplayFor(modelItem => item.result)
</td>
</tr>
}
</table>
Model
public class MarkModel
{
public string student_no { get; set; }
public string student_surname { get; set; }
public string student_firstname { get; set; }
public string assignment_no { get; set; }
public bool submitted { get; set; }
public string result { get; set; }
public Nullable<int> group_no { get; set; }
}
Create an EditorTemplate for type of MarkModel.
In /Views/Shared/EditorTemplates/MarkModel.cshtml
#model MvcApplication2.Models.MarkModel
<tr>
<td>#Html.DisplayFor(m => m.student_no)</td>
<td>#Html.DisplayFor(m => m.student_surname)</td>
<td>#Html.DisplayFor(m => m.student_firstname)</td>
<td>#Html.CheckBoxFor(m => m.submitted)</td>
<td>#Html.TextBoxFor(m => m.result)</td>
</tr>
and in the main view
#model IEnumerable<MvcApplication2.Models.MarkModel>
#using (Html.BeginForm())
{
<table>
<thead>
// add your th elements
</thead>
<tbody>
#Html.EditorFor(m => m)
<tbody>
</table>
<input type="submit" ../>
}
and create a method to post back to
[HttpPost]
public ActionResult P1A1Mark(IEnumerable<MarkModel>model)
Alternatively you can use a for loop in the view (the model must be IList<T>)
for(int i = 0; i < Model.Count; i++)
{
....
#Html.CheckBoxFor(m => m[i].submitted)
}

Categories