Commit ebc69772 authored by hasan khaddour's avatar hasan khaddour

adding medicine image upload feature

parent cfaeb045
......@@ -40,8 +40,8 @@ namespace ApplicationCore.Mapper
.ForMember(s=>s.MedicalStateMedicines , op=>op.Ignore())
.ForMember(s => s.Patient, op => op.Ignore());
CreateMap<Category, Category>();
CreateMap<Category, Category>()
CreateMap<Category, CategoryDTO>();
CreateMap<CategoryDTO, Category>()
.ForMember(dest => dest.Medicines, opt => opt.Ignore())
;
CreateMap<MedicineType, MedicineTypeDTO>().ReverseMap();
......
......@@ -9,7 +9,11 @@ using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using WebPresentation.Filters.ImageLoad;
using WebPresentation.Filters.ModelStateValidation;
using WebPresentation.Services;
using WebPresentation.ViewModels;
namespace WebPresentation.Controllers
{
public class CRUDController<TDto,TVModel> : BaseController where TDto : DTOBase where TVModel : ViewModels.BaseViewModel
......@@ -129,19 +133,20 @@ namespace WebPresentation.Controllers
[HttpPost]
[ValidateAntiForgeryToken]
[StateValidationFilter]
public IActionResult Edit(int id, TVModel viewModel)
[ImageLoadFilter]
public IActionResult Edit(int id, [FromForm] TVModel viewModel)
{
if (id != viewModel.Id)
{
return NotFound();
}
TDto dto = null;
TDto dto ;
if (ModelState.IsValid)
{
try
{
dto = _mapper.Map<TDto>(viewModel);
dto = _service.Update(dto);
......
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebPresentation.Services;
using WebPresentation.ViewModels;
namespace WebPresentation.Filters.ImageLoad
{
public class ImageLoadFilter :ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var imageUploaded = context.ActionArguments.Values.Where(p => p is IImageForm).FirstOrDefault();
var imageService = context.HttpContext.RequestServices.GetService(typeof(IImageService));
if(
(((IImageForm)imageUploaded).ImageFile != null )
&&
(((IImageForm)imageUploaded).ImageFile.Length != 0)){
var imagePath = ((IImageService)imageService).SaveImageAsync(((IImageForm)imageUploaded).ImageFile,context.Controller.GetType().Name).Result;
((IImageForm)imageUploaded).ImageName = imagePath; // You can pass other information as needed
}
}
}
}
......@@ -16,6 +16,7 @@ namespace WebPresentation.Filters.ModelStateValidation
if (!context.ModelState.IsValid)
{
Controller controller = context.Controller as Controller;
if (controller != null)
{
var model = context.ActionArguments.Values.Where(p=> p is not int ).FirstOrDefault();
......
......@@ -9,7 +9,19 @@ namespace ApplicationCore.Mappere
{
public ViewModelObjectMapper()
{
CreateMap<MedicineViewModel, MedicineDTO>().ReverseMap();
CreateMap<MedicineViewModel, MedicineDTO>()
.ForMember(dest => dest.Image, opt => opt.MapFrom(src => src.ImageName)) // Map ImageName from MedicineViewModel to Image in MedicineDTO
.ForMember(dest => dest.Ingredients, opt => opt.MapFrom(src => src.Ingredients))
.ForMember(dest => dest.Category, opt => opt.MapFrom(src => src.Category))
.ForMember(dest => dest.Dosage, opt => opt.MapFrom(src => src.Dosage))
.ForMember(dest => dest.MedicineType, opt => opt.MapFrom(src => src.MedicineType))
.ForMember(dest => dest.MedicineIngredients, opt => opt.MapFrom(src => src.MedicineIngredients));
CreateMap<MedicineDTO, MedicineViewModel>()
.ForMember(dest => dest.ImageName, opt => opt.MapFrom(src => src.Image))
.ForMember(dest => dest.Ingredients, opt => opt.MapFrom(src => src.Ingredients))
.ForMember(dest => dest.MedicineIngredients, opt => opt.MapFrom(src => src.MedicineIngredients));
CreateMap<PatientDTO, PatientViewModel>().ReverseMap();
CreateMap<IngredientViewModel, IngredientDTO>().ReverseMap();
......
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace WebPresentation.Services
{
public interface IImageService
{
Task<string> SaveImageAsync(IFormFile file, String folderName);
}
public class ImageService : IImageService
{
private readonly string _uploadsFolderPath;
private readonly String _rootPath;
public ImageService(IWebHostEnvironment env)
{
_uploadsFolderPath = Path.Combine(env.WebRootPath, "img");
_rootPath = env.WebRootPath;
}
public async Task<string> SaveImageAsync(IFormFile file,String folderName)
{
var uploadsFolderPath = Path.Combine(_uploadsFolderPath, folderName);
var uniqueFileName = Guid.NewGuid().ToString() + "_" + file.FileName;
var filePath = Path.Combine(uploadsFolderPath, uniqueFileName);
if (file.Length > 0)
{
Directory.CreateDirectory(uploadsFolderPath);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
}
return folderName +"/"+uniqueFileName; // Return relative path
}
}
}
......@@ -21,6 +21,7 @@ using System;
using Microsoft.AspNetCore.Http;
using ApplicationCore.Mappere;
using WebPresentation.Filters.ModelStateValidation;
using WebPresentation.Services;
namespace WebPresentation
{
......@@ -126,7 +127,7 @@ namespace WebPresentation
#endregion ADD Authentication Schema
services.AddSession();
services.AddScoped<IImageService,ImageService>();
services.AddScoped<StateValidationFilter>();
services.AddControllersWithViews().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
......
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebPresentation.ViewModels
{
public interface IImageForm
{
public IFormFile ImageFile {get ;set; }
public String ImageName { get; set; }
}
}
using System;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
namespace WebPresentation.ViewModels
{
public class MedicineViewModel : BaseViewModel
public class MedicineViewModel : BaseViewModel , IImageForm
{
public String TradeName { get; set; }
......@@ -12,12 +13,13 @@ namespace WebPresentation.ViewModels
public String SideEffect { get; set; }
public String Description { get; set; }
public int Price { get; set; }
public String Image { get; set; }
public int Dosage { get; set; }
public CategoryViewModel Category { get; set; }
public MedicineTypeViewModel MedicineType { get; set; }
public ICollection<IngredientViewModel> Ingredients { get; set; }
public ICollection<MedicineIngredientViewModel> MedicineIngredients { get; set; }
public IFormFile ImageFile { get ; set; }
public string ImageName { get ; set ; }
}
}
using ApplicationDomain.Entities;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -7,14 +8,15 @@ using System.Threading.Tasks;
namespace WebPresentation.ViewModels
{
public class PatientViewModel : BaseViewModel
public class PatientViewModel : BaseViewModel //,IImageForm
{
public String UserId { get; set; }
public User User { get; set; }
public String BIO { get; set; }
// public IFormFile ImageFile { get; set; }
// public string ImageName { get; set; }
public ICollection<MedicalStateViewModel> MedicalStates { get; set; }
}
}
......@@ -21,7 +21,7 @@
{
<div class="col-lg-4 col-md-6 d-flex flex-column align-items-stretch mb-5">
<div class="card m-3">
<img src="/img/portfolio/@item.Image"
<img src="/img/portfolio/@item.ImageName"
class="card-img-top img-fluid" style="max-height:250px "
alt="Waterfall" />
<div class="card-body">
......
......@@ -63,9 +63,9 @@
</div>
<div class="form-group mb-3">
<label asp-for="Image" class="control-label">Image URL</label>
<input asp-for="Image" class="form-control" />
<span asp-validation-for="Image" class="text-danger"></span>
<label asp-for="ImageFile" class="control-label">Image File</label>
<input asp-for="ImageFile" class="form-control" />
<span asp-validation-for="ImageFile" class="text-danger"></span>
</div>
<div class="form-group mb-4">
......
......@@ -15,7 +15,7 @@
<div class="row g-0">
<div class="col-md-4 gradient-custom text-center text-black"
style="border-top-left-radius: .5rem; border-bottom-left-radius: .5rem;">
<img src="~/img/portfolio/@Model.Image"
<img src="~/img/@Model.ImageName"
alt="Avatar" class="img-fluid my-5" style="width: 80px;" />
<h5>@Model.TradeName</h5>
<p>Category: @(Model.Category is null ? "":Model.Category.Name)</p>
......
......@@ -18,7 +18,7 @@
<div class="">
<div class="card shadow-sm">
<div class="card-body">
<form asp-action="Edit" class="row g-3">
<form asp-action="Edit" class="row g-3" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="col-md-6">
......@@ -32,11 +32,6 @@
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="col-md-6">
<label asp-for="MedicineType" class="form-label">Description</label>
<input asp-for="MedicineType" class="form-control" />
<span asp-validation-for="MedicineType" class="text-danger"></span>
</div>
<div class="col-md-6">
......@@ -81,10 +76,11 @@
<span asp-validation-for="SideEffect" class="text-danger"></span>
</div>
<div class="col-12">
<label asp-for="Image" class="form-label">Image URL</label>
<input asp-for="Image" class="form-control" />
<span asp-validation-for="Image" class="text-danger"></span>
<label asp-for="ImageFile" class="form-label">Image File</label>
<input type="file" asp-for="ImageFile" class="form-control" />
<span asp-validation-for="ImageFile" class="text-danger"></span>
</div>
<div class="col-12 mt-4">
......
#pragma checksum "C:\Users\HASAN\Desktop\Medic\WebPresentation\Views\Medicine\Details.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "5e75b0dcb377daeda9a27984f637bf1b5b1d6ba1"
#pragma checksum "C:\Users\HASAN\Desktop\Medic\WebPresentation\Views\Medicine\Details.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "b59ddab6f4ba44be6f22ef8a97ca3c884a481a11"
// <auto-generated/>
#pragma warning disable 1591
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(AspNetCore.Views_Medicine_Details), @"mvc.1.0.view", @"/Views/Medicine/Details.cshtml")]
......@@ -46,7 +46,7 @@ using System;
#line default
#line hidden
#nullable disable
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"5e75b0dcb377daeda9a27984f637bf1b5b1d6ba1", @"/Views/Medicine/Details.cshtml")]
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"b59ddab6f4ba44be6f22ef8a97ca3c884a481a11", @"/Views/Medicine/Details.cshtml")]
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"4a2f5fee0d7223f937b9f0309fc3b9062263e26d", @"/Views/_ViewImports.cshtml")]
public class Views_Medicine_Details : global::Microsoft.AspNetCore.Mvc.Razor.RazorPage<MedicineViewModel>
{
......@@ -103,16 +103,16 @@ using System;
<div class=""col-md-4 gradient-custom text-center text-black""
style=""border-top-left-radius: .5rem; border-bottom-left-radius: .5rem;"">
");
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("img", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "5e75b0dcb377daeda9a27984f637bf1b5b1d6ba16604", async() => {
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("img", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "b59ddab6f4ba44be6f22ef8a97ca3c884a481a116604", async() => {
}
);
__Microsoft_AspNetCore_Mvc_Razor_TagHelpers_UrlResolutionTagHelper = CreateTagHelper<global::Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper>();
__tagHelperExecutionContext.Add(__Microsoft_AspNetCore_Mvc_Razor_TagHelpers_UrlResolutionTagHelper);
BeginAddHtmlAttributeValues(__tagHelperExecutionContext, "src", 2, global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
AddHtmlAttributeValue("", 716, "~/img/portfolio/", 716, 16, true);
AddHtmlAttributeValue("", 716, "~/img/", 716, 6, true);
#nullable restore
#line 18 "C:\Users\HASAN\Desktop\Medic\WebPresentation\Views\Medicine\Details.cshtml"
AddHtmlAttributeValue("", 732, Model.Image, 732, 12, false);
AddHtmlAttributeValue("", 722, Model.ImageName, 722, 16, false);
#line default
#line hidden
......@@ -260,35 +260,35 @@ AddHtmlAttributeValue("", 732, Model.Image, 732, 12, false);
#line hidden
#nullable disable
WriteLiteral("</td>\r\n <td>\r\n <button class=\"btn btn-danger\"");
BeginWriteAttribute("ondblclick", " ondblclick=\'", 3643, "\'", 3800, 16);
WriteAttributeValue("", 3656, "DeleteConfirm(\"Delete", 3656, 21, true);
WriteAttributeValue(" ", 3677, "Confirm\",", 3678, 10, true);
WriteAttributeValue(" ", 3687, "\"Are", 3688, 5, true);
WriteAttributeValue(" ", 3692, "you", 3693, 4, true);
WriteAttributeValue(" ", 3696, "sure", 3697, 5, true);
WriteAttributeValue(" ", 3701, "you", 3702, 4, true);
WriteAttributeValue(" ", 3705, "want", 3706, 5, true);
WriteAttributeValue(" ", 3710, "to", 3711, 3, true);
WriteAttributeValue(" ", 3713, "delete", 3714, 7, true);
BeginWriteAttribute("ondblclick", " ondblclick=\'", 3637, "\'", 3794, 16);
WriteAttributeValue("", 3650, "DeleteConfirm(\"Delete", 3650, 21, true);
WriteAttributeValue(" ", 3671, "Confirm\",", 3672, 10, true);
WriteAttributeValue(" ", 3681, "\"Are", 3682, 5, true);
WriteAttributeValue(" ", 3686, "you", 3687, 4, true);
WriteAttributeValue(" ", 3690, "sure", 3691, 5, true);
WriteAttributeValue(" ", 3695, "you", 3696, 4, true);
WriteAttributeValue(" ", 3699, "want", 3700, 5, true);
WriteAttributeValue(" ", 3704, "to", 3705, 3, true);
WriteAttributeValue(" ", 3707, "delete", 3708, 7, true);
#nullable restore
#line 62 "C:\Users\HASAN\Desktop\Medic\WebPresentation\Views\Medicine\Details.cshtml"
WriteAttributeValue(" ", 3720, ing.Ingredient.Name, 3721, 20, false);
WriteAttributeValue(" ", 3714, ing.Ingredient.Name, 3715, 20, false);
#line default
#line hidden
#nullable disable
WriteAttributeValue(" ", 3741, "From", 3742, 5, true);
WriteAttributeValue(" ", 3746, "this", 3747, 5, true);
WriteAttributeValue(" ", 3751, "medicine\",", 3752, 11, true);
WriteAttributeValue(" ", 3762, "\"ReomveIngredient\",", 3763, 20, true);
WriteAttributeValue(" ", 3735, "From", 3736, 5, true);
WriteAttributeValue(" ", 3740, "this", 3741, 5, true);
WriteAttributeValue(" ", 3745, "medicine\",", 3746, 11, true);
WriteAttributeValue(" ", 3756, "\"ReomveIngredient\",", 3757, 20, true);
#nullable restore
#line 62 "C:\Users\HASAN\Desktop\Medic\WebPresentation\Views\Medicine\Details.cshtml"
WriteAttributeValue("", 3782, ing.IngredientId, 3782, 17, false);
WriteAttributeValue("", 3776, ing.IngredientId, 3776, 17, false);
#line default
#line hidden
#nullable disable
WriteAttributeValue("", 3799, ")", 3799, 1, true);
WriteAttributeValue("", 3793, ")", 3793, 1, true);
EndWriteAttribute();
WriteLiteral(">Delete</button>\r\n </td>\r\n\r\n </tr>\r\n");
#nullable restore
......@@ -304,7 +304,7 @@ WriteAttributeValue("", 3782, ing.IngredientId, 3782, 17, false);
<div class=""row pt-1"">
<div class=""col-6 mb-3"">
");
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("a", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "5e75b0dcb377daeda9a27984f637bf1b5b1d6ba116637", async() => {
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("a", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "b59ddab6f4ba44be6f22ef8a97ca3c884a481a1116630", async() => {
WriteLiteral("Back to List");
}
);
......@@ -320,7 +320,7 @@ WriteAttributeValue("", 3782, ing.IngredientId, 3782, 17, false);
Write(__tagHelperExecutionContext.Output);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
WriteLiteral("\r\n\r\n </div>\r\n <div class=\"col-6 mb-3\">\r\n ");
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("a", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "5e75b0dcb377daeda9a27984f637bf1b5b1d6ba117955", async() => {
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("a", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.StartTagAndEndTag, "b59ddab6f4ba44be6f22ef8a97ca3c884a481a1117948", async() => {
WriteLiteral("Add Ingredients ");
}
);
......
40babbaebe908ee8019123f902e7ae02ef0aa7c7
15cb97b8a060c155cc9b00ed27a476ac44f14fb8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment