How to get image from Form and store in Database - c#

I am trying to retrieve an image from a Form, but I always get a null instead.
The data is sent from Form as a parameter to the method AddArticles, that writes to the database after trying to parse the image into a byte array.
[HttpPost]
public async Task<IActionResult> Add([FromForm] ArticleViewModel artice, IFormFile file) {
int result = await AddArticles(artice, file);
if (result == 201 && ModelState.IsValid) {
return RedirectToAction("Index");
} else {
return View(artice);
}
}
public async Task<int> AddArticles(ArticleViewModel articles, IFormFile file {
if (articles != null && articles.Name != null && articles.Article != null && articles.category != null) {
DateTime dateTime = new DateTime();
articles.dateTimeOfCreate = dateTime.Date;
var client = new MongoClient("mongodb://localhost:27017/");
var database = client.GetDatabase("Article");
var collection = database.GetCollection<ArticleViewModel>("article");
if (articles.UrlImage != null) {
var ArticleModel = new ArticleModel();
using (var memoryStream = new MemoryStream()) {
file.CopyTo(memoryStream);
articles.UrlImage = memoryStream.ToArray();
//articles.imagecontext = memoryStream.ToArray();
}
await collection.InsertOneAsync(articles);
}
return 201;
} else {
return 400;
}
}
I want to write the image data into the database. After that, I want to convert that byte array nack into an Image and display it.
public class ArticleViewModel {
[BsonId]
public ObjectId _id { get; set; }
[BsonElement("Name")]
public string Name { get; set; }
[BsonElement("Article")]
public string Article { get; set; }
[BsonElement("Image")]
public byte[] UrlImage { get; set; }
[BsonElement("dateTimeOfCreate")]
public DateTime dateTimeOfCreate { get; set; }
[BsonElement("Category")]
public string category { get; set; }
}

Related

C# Updating model using HttpPost

I started learning C# and I want to update my model using the [HttpPost] annotation. I tried removing the [FromBody]Item itm parameter and the fields on the repository but it's not working either. Below is my code.
Controller:
[HttpPost("{id}")]
public ActionResult<Item> UpdateItem([FromBody]Item itm, int id)
{
var getItem = _repository.GetItemById(id);
if (getItem == null)
{
return NotFound();
}
_repository.UpdateItem(itm);
_repository.SaveChanges();
return Ok(getItem);
}
Repository:
public void UpdateItem(Item itm)
{
if (itm == null)
{
throw new ArgumentNullException(nameof(itm));
}
var itemToUpdate = this.GetItemById(itm.Id);
if (itm.Name != null)
{
itemToUpdate.Name = itm.Name;
}
itemToUpdate.Price = itm.Price;
itemToUpdate.Condition = itm.Condition;
itemToUpdate.Size = itm.Size;
itemToUpdate.DateSold = itm.DateSold;
itemToUpdate.SellMethod = itm.SellMethod;
_context.Items.Update(itemToUpdate);
}
Interface:
void UpdateItem(Item itm);
Model:
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int Price { get; set; }
public string Condition { get; set; }
public string Size { get; set; }
public string DateSold { get; set; }
public string SellMethod { get; set; }
First of all verify that you're sending that item correctly:
Is the form correct and pointing to that method of your controller?
Are you sending that item via the form (have you used the provided methods for this) ?
After that, if you're sending the item in the body of your post request, then verify the item in the method's parameter is available.
EDIT:
Well, as already discussed with Panagiotis you should rather directly use the DbContext itself as it already provides everything you need.
[HttpPost("{id}")]
public ActionResult<Item> UpdateItem(int id, [FromBody]Item itemData)
{
var foundItem = _dbContext.Items.SingleOrDefault(x => x.Id == id);
if (foundItem == null)
{
return NotFound();
}
foundItem.Name = itemData.Name;
foundItem.Size = itemData.Size;
// and so on
_dbContext.SaveChanges();
return Ok(foundItem);
}
Another way to keep your current structure, but it's not recommended, would be the following:
[HttpPost("{id}")]
public ActionResult<Item> UpdateItem(int id, [FromBody]Item itemData)
{
var updatedItem = _repository.UpdateItem(id, itemData);
if (updatedItem == null)
{
return NotFound();
}
return Ok(updatedItem);
}
public void UpdateItem(int id, Item itemData)
{
// you can validate parameters and throw errors if e.g. itemData == null
var originalItem = GetItemById(id); // this should internally get the item e.g. _dbContext.Items.Where(x => x.id == itemData.Id);
if(originalItem == null)
{
return null;
}
originalItem.Name = itemData.Name;
originalItem.Price = itemData.Price;
originalItem.Condition = itemData.Condition;
originalItem.Size = itemData.Size;
originalItem.DateSold = itemData.DateSold;
originalItem.SellMethod = itemData.SellMethod;
SaveChanges(); // guess this will be _dbContext.SaveChanges() instead
return originalItem;
}
Well, you could also change it to first load the item and then pass the originalItem and the itemData into the UpdateItem method inside your repository. But as you see the better way to directly use the DbContext is more clearer and shorter.

c# linq query extract repeating data types

I have a list of raw data, where always 8 data values are available for one timestamp Date_Time. I would like to use linq to sort the values of Data_Value column by the Data_Type into one row for each Date_Time.
Rawdata table
I have the following class and would like to return it as a list of that class.
public class MeasurementData
{
public MeasurementData();
public int Test_ID { get; set; }
public int Channel { get; set; }
public string Date_Time { get; set; }
public double Current { get; set; }
public double Voltage { get; set; }
public double Charge_Capacity { get; set; }
public double Discharge_Capacity { get; set; }
}
Here is a reduced form of the code, where i just try to extract four values.
public static List<DataStructure.MeasurementData> RawResult(List<DataStructure.MeasurementRawTableSQL> rawData, int _Test_ID)
{
if (rawData != null)
{
var result = rawData.GroupBy(x => x.Date_Time)
.Select(gr =>
{
var _Date_Time = TicksToDate(gr.FirstOrDefault().Date_Time);
var _Channel = gr.FirstOrDefault().Channel;
var _Voltage = gr.Where(x => x.Data_Type == 21).FirstOrDefault().Data_Value;
var _Current = gr.Where(x => x.Data_Type == 22).FirstOrDefault().Data_Value;
var _Charge_Capacity = gr.Where(x => x.Data_Type == 23).FirstOrDefault().Data_Value;
var _Discharge_Capacity = gr.Where(x => x.Data_Type == 24).FirstOrDefault().Data_Value;
return new DataStructure.MeasurementData
{
Test_ID = _Test_ID,
Channel = _Channel,
Date_Time = _Date_Time,
Current = _Current,
Voltage = _Voltage,
Charge_Capacity = _Charge_Capacity,
Discharge_Capacity = _Discharge_Capacity
};
}
).ToList();
return result;
}
else return null;
}
This is partially working, for the case 21 and 22 it gives me proper values, whereas I get an error "Object reference not set to an instance of an object" for the case 23 and 24. On the other hand the database has this rows for every single datapoint and is never null. If I only select First() instead of FirstOrDefault() I get an "sequence contains no elements".
I am really stuck right now and would really appriciate your help.
Below is the cleanest way of solving issue. I cannot explain why you are not getting a Data_Type for each time value, but code below should get around the exceptions. I used decimal? as the type. The exception is caused when the WHERE returns null you cannot get the property Data_Value. So you have to test for null like code below :
class Program
{
static void Main(string[] args)
{
}
//public DataStructures DataStructure = new DataStructures();
public static List<DataStructure.MeasurementData> RawResult(List<DataStructure.MeasurementRawTableSQL> rawData, int _Test_ID)
{
if (rawData != null)
{
double? _Voltage = null;
double? _Current = null;
double? _Charge_Capacity = null;
double? _Discharge_Capacity = null;
var result = rawData.GroupBy(x => x.Date_Time)
.Select(gr =>
{
var _Date_Time = gr.Key;
var _Channel = gr.FirstOrDefault().Channel;
var _Voltage_Row = gr.Where(x => x.Data_Type == 21).FirstOrDefault();
if(_Voltage_Row != null) _Voltage = _Voltage_Row.Data_Value;
var _Current_Row = gr.Where(x => x.Data_Type == 22).FirstOrDefault();
if(_Current_Row != null) _Current = _Current_Row.Data_Value;
var _Charge_Capacity_Row = gr.Where(x => x.Data_Type == 23).FirstOrDefault();
if (_Charge_Capacity_Row != null) _Charge_Capacity = _Charge_Capacity_Row.Data_Value;
var _Discharge_Capacity_Row = gr.Where(x => x.Data_Type == 24).FirstOrDefault();
if (_Discharge_Capacity_Row != null) _Discharge_Capacity = _Discharge_Capacity_Row.Data_Value;
return new DataStructure.MeasurementData
{
Test_ID = _Test_ID,
Channel = _Channel,
Date_Time = _Date_Time,
Current = _Current,
Voltage = _Voltage,
Charge_Capacity = _Charge_Capacity,
Discharge_Capacity = _Discharge_Capacity
};
}
).ToList();
return result;
}
else return null;
}
}
public class DataStructure
{
public class MeasurementData
{
public int? Test_ID { get; set; }
public int? Channel { get; set; }
public DateTime Date_Time { get; set; }
public double? Current { get; set; }
public double? Voltage { get; set; }
public double? Charge_Capacity { get; set; }
public double? Discharge_Capacity { get; set; }
}
public class MeasurementRawTableSQL
{
public DateTime Date_Time { get; set; }
public int Channel { get; set; }
public int Data_Type { get; set; }
public double Data_Value { get; set; }
}
}

update single column of Stub Entity in asp.net mvc

I have Book and each book can have multiple Chapter. Each of the Chapter has a single audio file. How can I update single row of chapter sub entity?
This is my model:
public class Book
{
public Book()
{
this.Chapters = new List<Chapter>();
}
[Key]
public Int64 ISBN { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BookID { get; set; }
public string bookName { get; set; }
public string bookAuthor { get; set; }
[DataType(DataType.Currency)]
public decimal bookPrice { get; set; }
public virtual ICollection<Chapter> Chapters { get; set; }
}
public class Chapter
{
public int ChapterId { get; set; }
public string chapterName { get; set; }
[ForeignKey("Book")]
public Int64 ISBN { get; set; }
public virtual Book Book { get; set; }
}
In Create ActionResult I add new Chapter by create new object from Chapter model and add it using book.Chapters.Add()
for (int i = 1; i < Request.Files.Count; i++)
{
var mfile = Request.Files[i];
if (mfile != null && mfile.ContentLength > 0)
{
var fileName = Path.GetFileNameWithoutExtension(mfile.FileName);
Chapter _bChapter = new Chapter()
{
chapterName = fileName,
chapterLink = BookDir + mfile.FileName
};
book.Chapters.Add(_bChapter);
mfile.SaveAs(Server.MapPath(_bChapter.chapterLink));
}
}
in Edit ActionResult I get new audio using HttpPostedFileBase
public ActionResult Edit(Book book, IEnumerable<HttpPostedFileBase> file)
{
if (ModelState.IsValid)
{
db.Entry(book).State = EntityState.Modified;
//do some File operation to save audio in server folder
db.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
But I dont know how to save new uploaded audio to chapter sub entity
You can update Chapter, first find related chapter by using SingleOrDefault method, next edit chapterName property and call SaveChanges() method, like this:
using (var context = new YourDbContext())
{
var result = context.Chapter.SingleOrDefault(b => b.ISBN == book.ISBN);
if (result != null)
{
result.chapterName = #"/root/my/audios";
context.SaveChanges();
}
}
EDIT:
using (var context = new YourDbContext())
{
var result = context.Chapter.Where(b => b.ISBN == book.ISBN).ToList();
if (result.Any())
{
foreach(var chapter in result)
{
chapter.chapterName = #"/root/my/audios";
}
context.SaveChanges();
}
}

Null JSON GET ASP.NET MVC

Hi I have two controller methods. I am passing two parameters from the 1st method to the 2nd. The values inserted to database are correct and not NULL. However when there are displayed back on the webpage in the return Json line, they come out as null and im not sure as to why? Here are the controller methods:
[HttpPost]
public void CalculateAndSaveToDB(BMICalculation CalculateModel)
{
if (ModelState.IsValid)
{
CalculateModel.Id = User.Identity.GetUserId();
CalculateModel.Date = System.DateTime.Now;
CalculateModel.BMICalc = CalculateModel.CalculateMyBMI(CalculateModel.Weight, CalculateModel.Height);
CalculateModel.BMIMeaning = CalculateModel.BMIInfo(CalculateModel.BMICalc);
db.BMICalculations.Add(CalculateModel);
db.SaveChanges();
}
CalculateAndSaveToDB(CalculateModel.BMICalc.ToString(), CalculateModel.BMIMeaning.ToString());
}
public JsonResult CalculateAndSaveToDB(string o, string t)
{
var data = new
{
CalculatedBMI = o,
CalculatedBMIMeaning = t
};
return Json(data, JsonRequestBehavior.AllowGet);
}
Update
BMICalculationsModel:
public partial class BMICalculation
{
public string Id { get; set; }
public System.DateTime Date { get; set; }
public Nullable<double> BMICalc { get; set; }
[Required]
public double Height { get; set; }
[Required]
public double Weight { get; set; }
public int BMICalculationID { get; set; }
public virtual AspNetUser AspNetUser { get; set; }
public string BMIMeaning { get; set; }
public double CalculateMyBMI(double KG, double Height)
{
return KG / (Height * Height);
}
public string BMIInfo(double? BMI)
{
string BMIInfo = "";
if (BMI <= 18.5)
{
BMIInfo = "Underweight";
}
else if (BMI > 18.5 && BMI < 25)
{
BMIInfo = "Average";
}
else if (BMI > 25)
{
BMIInfo = "Overweight";
}
return BMIInfo;
}
}
You need to make your first method return JsonResult and not void. The second CalculateAndSaveToDB returns a JsonResult which never gets used.
I would definitely not call that second method CalculateAndSaveToDB as it doesn't save anything to the DB. Maybe GenerateJsonCalc would be more suitable or maybe no method at all:
[HttpPost]
public JsonResult CalculateAndSaveToDB(BMICalculation CalculateModel)
{
if (ModelState.IsValid)
{
CalculateModel.Id = User.Identity.GetUserId();
CalculateModel.Date = System.DateTime.Now;
CalculateModel.BMICalc = CalculateModel.CalculateMyBMI(CalculateModel.Weight, CalculateModel.Height);
CalculateModel.BMIMeaning = CalculateModel.BMIInfo(CalculateModel.BMICalc);
db.BMICalculations.Add(CalculateModel);
db.SaveChanges();
}
return CalculateAndSaveToDB(CalculateModel.BMICalc.ToString(), CalculateModel.BMIMeaning.ToString());
I would go for something like:
return Json(new
{
CalculatedBMI = CalculateModel.BMICalc.ToString(),
CalculatedBMIMeaning = CalculateModel.BMIMeaning.ToString()
}, JsonRequestBehavior.AllowGet);
Change your return type of your POST method and its last line to this:
public ActionResult CalculateAndSaveToDB(BMICalculation CalculateModel)
{
//stuff
return RedirectToAction("CalculateAndSaveToDB", new { o = CalculateModel.BMICalc.ToString(), t = CalculateModel.BMIMeaning.ToString());
}
try return a dynamic object
public dynamic CalculateAndSaveToDB(BMICalculation CalculateModel)
{
...
return CalculateAndSaveToDB(CalculateModel.BMICalc.ToString(), CalculateModel.BMIMeaning.ToString());
}
public dynamic CalculateAndSaveToDB(string o, string t)
{
dynamic data = new new ExpandoObject();
data.CalculatedBMI = o;
data.CalculatedBMIMeaning = t;
return data ;
}

How to get a property from a list by a property?

I have a class:
public class Server
{
public string ServerId { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public string Type { get; set; }
public string Region { get; set; }
}
Now I have a List<Server> and want to get the property "status" for a given ServerID.
How?
Using Linq:
string GetServerStatus(string id)
{
var server = servers.FirstOrDefault(s => s.ServerId == id);
if (server != null)
return server.Status;
return null;
}
Server serverById=servers.FirstOrDefault(x=>x.ServerId=="1");
if(serverById!=null)
{
MessageBox.Show(serverById.Status);
}
public string GetStatus(string serverID, List<Server> collection)
{
string result = string.Empty;
foreach(Server server in collection)
{
if (server.ServerID == serverID)
{
result = server.Status;
break;
}
}
return result;
}
public Server FindServerByID(List<Server> list, string id)
{
for (int i = 0; i < list.Count; i++)
if (item[i].ServerID == id)
return item;
return null;
}
public string GetStatusForServerByID(List<Server> list, string id)
{
var server = GetServerByID(list, id);
return server == null
? null
: server.Status;
}
You can use a from clause (see http://msdn.microsoft.com/en-us/library/bb383978.aspx):
List<Server> yourlist = new List<Server>()
var data = from x in yourlist where x.ServerId == "1" select x.Status;

Categories

Resources