Uploading image in MVC .NET core using EF [closed] - entity-framework

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
How can i create database using EF with info and picture as column in db? Also I need to upload image into local db. I started building app with Microsoft's tutorial where you upload "movie".
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc?tabs=aspnetcore2x
How can i show some photo from db even hardcoded like in example like this (SeedData.cs)?

Your Image Model Class :
public class YourImageModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public byte[] Image { get; set; }
}
In the Controller :
public async Task<IActionResult> UploadImage(YourImageModel yourImageModel, IFormFile imageToBeUploaded)
{
if (!ModelState.IsValid)
{
return View(yourImageModel);
}
if (imageToBeUploaded != null)
{
using (var memoryStream = new MemoryStream())
{
await imageToBeUploaded.CopyToAsync(memoryStream);
var imageToBeUploadedByteArray = memoryStream.ToArray();
yourImageModel.Image= imageToBeUploadedByteArray ;
}
}
_dbContext.YourImageModel.Add(yourImageModel)
await _dbContext.SaveChangesAsync();
return View();
}

your question is very broad but I will attempt to answer the main points.
for creating a table to store the image you need an entity like:
public class ImageEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string ImageInfo { get; set; }
public byte[] Image { get; set; }
}
to upload your image you need to convert it to a byte[] first then it is the same as adding any object to a table once its in the right format. to convert the to a byte[] you can use something like
public byte[] BitmapToByteArray(Bitmap image)
{
//converts bitmap to byteArray
byte[] byteArray;
using (MemoryStream memoryStream = new MemoryStream())
{
image.Compress(Bitmap.CompressFormat.Png, 0, memoryStream);
byteArray = memoryStream.ToArray();
}
return byteArray;
}

Related

How to get a upload button in swagger for IFormFile combined with other properties?

I have created a Asp.net core 3.1 web api with Swagger to upload files to server. the following code is working fine:
[HttpPost("PostFile")]
public ActionResult PostFile(IFormFile uploadedFile)
{
var saveFilePath = Path.Combine("c:\\savefilepath\\", uploadedFile.FileName);
using (var stream = new FileStream(saveFilePath, FileMode.Create))
{
uploadedFile.CopyToAsync(stream);
}
return Ok();
}
I get a nice upload button in swagger when I try to run this.
However, now I wanted to use a different model. that has some more properties along with the IFormFile.
public class FileUploadRequest
{
public string UploaderName { get; set; }
public string UploaderAddress { get; set; }
public IFormFile File { get; set; }
}
When I try to use this model, I dont see any upload button in Swagger that will help me to attach the file in the request.
For some reason, it shows the IFormFile as String. How can I get a upload button here?
In ASP.NET Core Web API, it binds application/json format data by default. But what your model need is multipart/form-data type data. So you need [FromForm] attribute to specific the source.
I use Swashbuckle.AspNetCore version 5.6.3 in ASP.NET Core 3.1:
[HttpPost]
public ActionResult PostFile([FromForm]FileUploadRequest model)
{
}
Result:
You can use IFormFile again in [HttpPost] so you can see the button.
public class FileUploadRequest
{
public string? UploaderName { get; set; }
public string? UploaderAddress { get; set; }
public IFormFile? File { get; set; }
}
[HttpPost]
public IActionResult PostFile(IFormFile file, FileUploadRequest model)
{
var saveFilePath = Path.Combine("c:\\savefilepath\\", model.UploaderAddress!);
using (var stream = new FileStream(saveFilePath, FileMode.Create))
{
file.CopyToAsync(stream);
}
return Ok();
}

Why mongodb store binary data in the form of base64?

I'm trying to learn how mongodb store each and every data type under the hood.
I have found it stores data in BSON format.
In order to store binary data in mongodb, it requires users to convert byte array in base64 then pass that base64 converted string to BinData(subtype,content in base64) class.
What is the reason behind storing binary data in this format. Why mongodb doesn't allow us to store raw binary?
According to the BSON specification, binary is stored as a 32-bit length followed by a type identifier and then by a series of bytes. Not a base64 string, bytes.
A shamelessly copied function from codementor.io shows that in languages that have the capability to handle binary data directly, it can be directly stored:
public class Question
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Category { get; set; }
public string Type { get; set; }
public string QuestionHeading { get; set; }
public byte[] ContentImage { get; set; }
public decimal Score { get; set; }
}
public class QuestionService
{
private readonly IMongoCollection<Question> _questions;
public QuestionService(IDatabaseSettings settings)
{
var client = new MongoClient("<YOUR CONNECTION STRING>");
var database = client.GetDatabase("<YOUR DATABASE NAME>");
_questions = database.GetCollection<Question>("Questions");
}
public Question Get(string id)
{
var result = _questions.Find(
q => q.Id == id).FirstOrDefault();
return result;
}
public Question Create(Question question)
{
_questions.InsertOne(question);
return question;
}
}
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var service = new QuestionService();
// CONVERT JPG TO A BYTE ARRAY
byte[] binaryContent = File.ReadAllBytes("image.jpg");
var question = new Question
{
Category = "Children's Quizzes",
Type = "Puzzles",
QuestionHeading = "Find the cat in the below image",
ContentImage = binaryContent, // Store the byte array in ContentImage property
Score = 10
};
service.Create(question);
}
BinData() is a constructor that permits specifying binary data directly in the source code text.
geeksforgeeks.org has an example for how to Upload and Retrieve Image on MongoDB using Mongoose

Swagger-net breaks when using [FromUri] with a complex EF model

I'm using Swagger-Net in my .NET 4.5.1 WebAPI project and one of my API calls is causing the Swagger UI to spin forever on load before coming back with the error below.
Specifically, I found that using [FromUri] in combination with a complex EF entity that has references to other entities ends up causing this.
[HttpPost]
public APIResponse CreateSchool([FromUri]School school)
{
// save school object to db
}
public partial class School : IAuditableEntity,IEntity
{
public School()
{
this.Affiliations = new HashSet<Affiliation>();
this.SchoolAccreditations = new HashSet<SchoolAccreditation>();
this.SchoolAdultRoles = new HashSet<SchoolAdultRole>();
this.SchoolCareOptions = new HashSet<SchoolCareOption>();
this.SchoolDailySessions = new HashSet<SchoolDailySession>();
this.SchoolEligibilityRequirements = new HashSet<SchoolEligibilityRequirement>();
// ...more hashsets
[DataMember]
public int SchoolID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public bool Active { get; set; }
//...more properties
}
}
Is there a way to still use FromUri and the EF model? Or do I need to change my API call signature?

Adding a model with join to another model for many to many without navigation property [duplicate]

This question already has an answer here:
Entity Framework - Inserting model with many to many mapping
(1 answer)
Closed 4 years ago.
How can I insert a model Tag that belongs to a model Post when I have the models setup like this:
Post
public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public Post()
{
Tags = new List<Tag>();
}
}
Tag
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
}
This question suggests to create a Post object then add Tags to the Tags collection, I couldn't get it working:
Insert/Update Many to Many Entity Framework . How do I do it?
I want to add Tag to Post already in the database, how can I do that with EF. I'm new to EF.
This is what I've tried, if I send this to the API it doesn't insert any records and I can see that the new tag Id = 0 which doesn't exist in the database, but I'd think that'd cause a foreign key constraint error, not sure If I need to do something to auto generate Id for the tag:
{
Name: "test"
}
API
[ResponseType(typeof(Tag))]
public IHttpActionResult PostTag(Tag tag)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var post = new Post();
var tags = new List<Tag>();
tags.Add(tag);
post.Tags.Add(tag);
post.Id = 10;
db.Entry(post).State = EntityState.Modified;
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = tag.Id }, tag);
}
I fetch the Post first add then save changes.
[ResponseType(typeof(Tag))]
public IHttpActionResult PostTag(TagDTO tagDTO)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var post = db.Posts.Find(TagDTO.PostId);
post.Tags.Add(new Tag() { Name = tagDTO.Name });
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = post.Tags.First().Id }, post);
}

Add/Update list in database using Entity framework 6

I have three tables QuestionBank,Question and Answer. " QuestionBank " will have list of Question and " Question " will have list of " Answer ".
QUESTIONBANK :-
public class QuestionBank
{
public int id { get; set; }
public string Text { get; set; }
public string Chapter { get; set; }
public string Standard { get; set; }
public List<Question> Question { get; set; }
public QuestionBank()
{
this.Question = new List<Question>();
}
}
QUESTION :-
public class Question
{
public int id { get; set; }
public string Title { get; set; }
public string QuestionText { get; set; }
public List<Answer> Answer { get; set; }
public string CorrectAnswer { get; set; }
public Question()
{
this.Answer = new List<Answer>();
}
}
ANSWER :-
public class Answer
{
public int id { get; set; }
public string AnswerText { get; set; }
}
WEB API :- //Edited
private IRepository<QuestionBank> _QuestionBankRepository;
public QuestionController(IRepository<QuestionBank> QuestionBankRepository)
{
_QuestionBankRepository = QuestionBankRepository;
}
[HttpPost]
[Route("Ques/Add")]
public Boolean Add(QuestionBank AddQuetionBankData)
{
var isQuetionBankPresent = _QuestionBankRepository.GetAll(p => p.Text == AddQuetionBankData.Text && p.Standard == AddQuetionBankData.Standard && p.Chapter == AddQuetionBankData.Chapter).FirstOrDefault<QuestionBank>();
if (isQuetionBankPresent != null)
{
/* Add the data in Question and Answer tables */
return false;
}
else
{
/* Add the data in all three tables */
return true;
}
}
I have this database for the web api. Now I want to add the data in database through json { "QuestionBank": QuestionBank, "Question": Question, "Answer": Answer } if the row is present in QuestionBank i dont want to add that data in QuestionBank table and only add the data in Question and Answer table with respective foreign keys. I am using the entity frame work and mvc 5 web api. I am stuck at this point. Please if any thing is needed let me know. Thanks in advance.
The Entity Framework way to update is to to Context.Entry([your object]).State = System.Data.Entity.EntityState.Modified; providing that the object is of the right type.
public Boolean Add(QuestionBank AddQuetionBankData)
{
bool flag = false;
var question = this.MapToQuestion(AddQuetionBankData); //map the input to the EF Type Question
var anwer = this.MapToAnswer(AddQuetionBankData); //map the input to the EF Type Answer
var isQuetionBankPresent = _QuestionBankRepository.GetAll(p => p.Text == AddQuetionBankData.Text && p.Standard == AddQuetionBankData.Standard && p.Chapter == AddQuetionBankData.Chapter).FirstOrDefault<QuestionBank>();
if (isQuetionBankPresent != null)
{
_context.Entry(question).State = EntityState.Modified;
_context.Entry(answer).State = EntityState.Modified;
/* Add the data in Question and Answer tables */
flag = false;
}
else
{
_context.Entry(question).State = EntityState.Modified;
_context.Entry(answer).State = EntityState.Modified;
_context.Entry(AddQuetionBankData).State = EntityState.Modified;
/* Add the data in all three tables */
flag = true;
}
_context.SaveChanges();
return flag;
}
private Question MapTo Question(QuestionBank q) //do this for Answers too
{
var _q = _context.Question.Where(a=>a.Id == q.Id).SingleOrDefault();
if(_q!=null)
{
_q.id = q.id; //this is already true
_q.Title = q.Title;
_q.QuestionText = q.Standard; //I guess
}
return _q;
}
The EF updates the Entity (the class you pass to the method Entry()) accordingly to its Type.
Notice that the position of the SaveChanges(): it works like a stored procedure, you do all the updates and the SaveChanges() is like the SQL COMMIT command.
You should also wrap the SaveChanges in a try/catch to handle errors, and dispose the _context.
EDIT
This class has as dependency IRepository<Question>, IRepository<QuestionBank>, and IRepository<Answer>.
You should create an UpdateController(or PublishController or whatever) that gets the three dependencies in the constructor (better a Facade Service), and call the Add() method for each one of them.
If you access directly the raw Database object you could do like I did and use the Entry() method for each table.