ASP.MVC Image edit - asp.net

public ActionResult Edit([Bind(Include = "id,category,title,image,active,ImageFile")] page_image page_image)
{
if (ModelState.IsValid)
{
if (page_image.ImageFile != null)
{
string fileName = Path.GetFileNameWithoutExtension(page_image.ImageFile.FileName);
string extension = Path.GetExtension(page_image.ImageFile.FileName);
fileName = fileName + DateTime.Now.ToString("yymmssff") + extension;
page_image.image = "/Uploads/page_images/" + fileName;
fileName = Path.Combine(Server.MapPath("/Uploads/page_images"), fileName);
page_image.ImageFile.SaveAs(fileName);
}
db.Entry(page_image).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.category = new SelectList(db.page, "id", "title", page_image.category);
return View(page_image);
}
Here I'm able to edit the User but is not showing the previous Image so If I click submit with out loading a new Image it will delete the previous one. What I have to do is the Edit view, I want it to show the name of the image. Can you guide me to the right direction?

The problem is because you save the view model as is to the Database, you should have a DTO. Anyway, try to get the ImageFile from the DB again, in case it submitted null.
if(page_image.ImageFile != null)
{
// your uploading logic
}
else
{
var oldData = db.Set<page_image>().Where(x => x.id == page_image.id).FirstOrDefault();
page_image.ImageFile = oldData.ImageFile;
}

If page_image.Image is null then get previous image and assign
if (page_image.ImageFile != null)
{
string fileName = Path.GetFileNameWithoutExtension(page_image.ImageFile.FileName);
string extension = Path.GetExtension(page_image.ImageFile.FileName);
fileName = fileName + DateTime.Now.ToString("yymmssff") + extension;
page_image.image = "/Uploads/page_images/" + fileName;
fileName = Path.Combine(Server.MapPath("/Uploads/page_images"), fileName);
page_image.ImageFile.SaveAs(fileName);
} else {
// get existing image from database
var data = db.page_image.AsNoTracking().Where(b => b.id == page_image.id).FirstOrDefault();
//assign to existing image
page_image.image = data.image ;
}
db.Entry(page_image).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
Update :
Error is throwing here because of same instance of dbcontext. You can create new instance to fetch or do as following.
var data = db.page_image.AsNoTracking().Where(b => b.id == page_image.id).FirstOrDefault();
or
using (var db2 = new YourDbContext())
{
var data = db2.page_image.Where(b => b.id == page_image.id).FirstOrDefault();
}

Related

ASP.NET core with MVC folder pathing/mapping FAIL

Whenever I upload a file I want to have it automatically converted into .pdf (I am doing that using NuGet). The thing is the upload scheme is done using relative paths. I do not know what to put into these parentheses:
var wordDocument = appWord.Documents.Open(uploadedFile);
What should I replace uploadedFile with in order to work? I will leave my relative path mapping code below:
public IActionResult Index1()
{
// Get files from the server
var model = new FilesViewModel();
foreach (var item in Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "upload")))
{
model.Files.Add(
new FileDetails { Name = System.IO.Path.GetFileName(item), Path = item });
}
return View(model);
}
[HttpPost]
public IActionResult Index1(IFormFile[] files)
{
// Iterate each files
foreach (var file in files)
{
// Get the file name from the browser
var fileName = System.IO.Path.GetFileName(file.FileName);
// Get file path to be uploaded
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "upload", fileName);
// Check If file with same name exists and delete it
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
}
// Create a new local file and copy contents of uploaded file
using (var localFile = System.IO.File.OpenWrite(filePath))
using (var uploadedFile = file.OpenReadStream())
{
var appWord = new Application();
if (appWord.Documents != null)
{
//yourDoc is your word document
var wordDocument = appWord.Documents.Open(uploadedFile);
string pdfDocName = "pdfDocument.pdf";
if (wordDocument != null)
{
wordDocument.ExportAsFixedFormat(pdfDocName,
WdExportFormat.wdExportFormatPDF);
wordDocument.Close();
}
appWord.Quit();
}
uploadedFile.CopyTo(localFile);
}
}
ViewBag.Message = "Files are successfully uploaded";
// Get files from the server
var model = new FilesViewModel();
foreach (var item in Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "upload")))
{
model.Files.Add(
new FileDetails { Name = System.IO.Path.GetFileName(item), Path = item });
}
return View(model);
}
public async Task<IActionResult> Download(string filename)
{
if (filename == null)
return Content("filename is not availble");
var path = Path.Combine(Directory.GetCurrentDirectory(), "upload", filename);
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, GetContentType(path), Path.GetFileName(path));
}
private string GetContentType(string path)
{
var types = GetMimeTypes();
var ext = Path.GetExtension(path).ToLowerInvariant();
return types[ext];
}
private Dictionary<string, string> GetMimeTypes()
{
return new Dictionary<string, string>
{
{".txt", "text/plain"},
{".pdf", "application/pdf"},
{".doc", "application/vnd.ms-word"},
{".docx", "application/vnd.ms-word"},
{".xls", "application/vnd.ms-excel"},
{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
{".png", "image/png"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".gif", "image/gif"},
{".csv", "text/csv"}
};
}

.NET Already Open DataReader

I get this error when running this code. I have looked for solution though I don't like the idea of using MARS as people have suggested as it may contain a lot of data, is there any other option here? Also can I edit a variable in a database without rewriting all of them as I do here, will this save server power or make no difference?
There is already an open DataReader associated with this Command which must be closed first.
public ActionResult CheckLinks(Link model)
{
var userId = User.Identity.GetUserId();
var UserTableID = db.UserTables.Where(c => c.ApplicationUserId == userId).First().ID;
foreach (var item in db.Links.Where(p => p.UserTable.ID == UserTableID))
{
string pageContent = null;
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(item.Obdomain);
HttpWebResponse myres = (HttpWebResponse)myReq.GetResponse();
using (StreamReader sr = new StreamReader(myres.GetResponseStream()))
{
pageContent = sr.ReadToEnd();
}
string live = "";
if (pageContent.Contains(item.Obpage))
{
live = "Yes";
}
else { live = "No"; }
var link = new Link { Obdomain = item.Obdomain, ClientID = item.ClientID, Obpage = item.Obpage, BuildDate = item.BuildDate, Anchor = item.Anchor, IdentifierID = item.IdentifierID, live = (Link.Live)Enum.Parse(typeof(Link.Live), live), UserTableID = item.UserTableID };
db.Entry(link).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index");
}
Entity Framework allows only one active command per context at a time. You should add .ToList() at the end of the following statement:
db.Links.Where(p => p.UserTable.ID == UserTableID).ToList();
So your code could look like this:
var items = db.Links.Where(p => p.UserTable.ID == UserTableID).ToList();
foreach (var item in items)

Invalid object name 'AspNetRoleClaims' exception when logging in

So I implemented Identity for my core project. I have successfully completed my Registration. So while trying to login using the _signInManager.PasswordSignInAsync I am getting the exception Invalid object name 'AspNetRoleClaims'.
I know this is because the AspNetRoleClaims table is not present in my database. But idont know the structure of this table nor do I know how to create it automatically like in mvc.
Can somebody enlighten me why this table is used. Or at least what is the expected structure.
public async Task<IActionResult> RegisterSubmit(Registermodel rm)
{
if (rm.role == "" || rm.role.Trim() == "-1")
{
return View();
}
else
{
var user = new ApplicationUser { UserName = rm.username, Email = rm.username, DeptName = rm.role };
var result = await _userManager.CreateAsync(user, rm.Password);
if (result.Succeeded)
{
_userManager.GenerateEmailConfirmationTokenAsync(user);
await _signInManager.SignInAsync(user, isPersistent: false);
var roleexists = await _roleManager.RoleExistsAsync(rm.role);
if (!roleexists)
{
var role = new IdentityRole();
role.Name = rm.role;
await _roleManager.CreateAsync(role);
}
await _userManager.AddToRoleAsync(user, rm.role);
user.Claims.Add(new IdentityUserClaim<string>
{
ClaimType = "ProductUploadRequest",
ClaimValue = "Allow"
});
}
return View("Login");
}
}
This is my login method.
public async Task<IActionResult> Login(LoginIdentityModel lim)
{
var result = await _signInManager.PasswordSignInAsync(lim.username, lim.password,false, lockoutOnFailure: false); //exception comes here
if (result.Succeeded)
{
var user = await _userManager.GetUserAsync(HttpContext.User);
UserProfileInfo userProfileInfo = new UserProfileInfo();
userProfileInfo.UserId = new Guid(user.Id);
userProfileInfo.FirstName = "test";
userProfileInfo.UserName = lim.username;
userProfileInfo.LastVisit = DateTime.Now;
string query2 = "select ud.UserId,dp.Id DeptId,dp.Name DeptName,rd.Id RoleId,rd.Name RoleName,ud.[ReadWrite] from UserInDepartment ud inner join Department dp on ud.DeptId=dp.Id inner join RolesInDepartment rd on dp.Id=rd.DeptId and ud.RoleId=rd.Id where ud.UserId='" + user.Id + "' and dp.IsEnable=1 and rd.IsEnable=1 and ud.IsEnable=1";
var userProfile = await _departMentalContext.UserProfiles.FromSql(query2).SingleOrDefaultAsync();
if (userProfile != null)
{
Dictionary<int, string> deptValues = new Dictionary<int, string>() { { userProfile.DeptId, userProfile.DeptName } };
userProfileInfo.Dept = deptValues;
Dictionary<int, string> roleValues = new Dictionary<int, string>() { { userProfile.RoleId, userProfile.RoleName } };
userProfileInfo.Role = roleValues;
userProfileInfo.ReadOrWrite = userProfile.ReadWrite;
HttpContext.Session.SetObject(UserProfileSessionName, userProfileInfo);
}
return View("/Home/DashBoard");
}
return View();
}
As you are using EF, you should be able to update your model database.
You can use CLI command (learn.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet).
Or if you are using Visual Studio, in the package manager console, you can execute those commands :
Add-Migration "init"
Update-Database
Commands allows you tu update table in your database. Also, it will create migrations files, which are a "picture" of your models. When the command Update-Database is executed, it loads the last migration file.

Values returned from my Repository model class is being cached

I have the following Post Edit action method:-
[HttpPost]
[ValidateAntiForgeryToken]
[CheckUserPermissions(Action = "Edit", Model = "StorageDevice")]
public ActionResult Edit(SDJoin sdj, FormCollection formValues)
{
//code goes here
if (ModelState.IsValid)
{
repository.Save();
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var databaseValues = (TMSStorageDevice)entry.GetDatabaseValues().ToObject();
var clientValues = (TMSStorageDevice)entry.Entity;
var databaseTechnology2 = repository.FindTechnology2(sdj.StorageDevice.TMSStorageDeviceID);
if (sdj.NetworkInfo.IPAddress != databaseTechnology2.TechnologyIPs.SingleOrDefault(a=>a.IsPrimary == true).IPAddress )
ModelState.AddModelError("NetworkInfo.IPAddress", "Value Has Changed "
);
if (sdj.NetworkInfo.MACAddress != databaseTechnology2.TechnologyIPs.SingleOrDefault(a => a.IsPrimary == true).MACAddress)
ModelState.AddModelError("NetworkInfo.MACAddress", "Value Has Changed "
);
if (databaseValues.RackID != clientValues.RackID)
ModelState.AddModelError("StorageDevice.RackID", "Value Has Changed "
);
But currently the values returned from the
var databaseTechnology2 = repository.FindTechnology2(sdj.StorageDevice.TMSStorageDeviceID);
will return a cached value inside the server , instead of retrieving the current database value. The repository method is :-
public Technology FindTechnology2(int id)
{
return tms.Technologies.Include(a=>a.TechnologyIPs).SingleOrDefault(a => a.TechnologyID == id);
}
Can anyone advice ?
I'm posting this as a follow up to my comment in order to show code properly.
You can set MergeOptions.OverwriteChanges as follows:
var objectContext = ((IObjectContextAdapter)entities).ObjectContext; //assuming 'entities' is your context here
var set = objectContext.CreateObjectSet<TechnologyRoles>();
set.MergeOption = MergeOption.OverwriteChanges;
var query = set.SingleOrDefault(a => a.TechnologyID == id);
Hope this helps,

Cannot find part of path while uploading image to a folder in Asp.net

I am uploading a profile picture of a user to a folder and saving its path to RavenDB. But my code is giving me an error that part of path is not found. On this line
file.SaveAs(path);
Code:
[HttpPost]
public ActionResult UploadPic(FileManagement fmanage, HttpPostedFileBase file)
{
string email = User.Identity.Name;
if (file != null && file.ContentLength > 0)
{
var FileName = string.Format("{0}.{1}", Guid.NewGuid(), file.ContentType);
var path = Path.Combine(Server.MapPath("~/App_Dta/Uploads"), FileName);
file.SaveAs(path);
using (var session = DocumentStore.OpenSession("RavenMemberShip"))
{
var query = from q in Session.Query<Registration>() where q.Email == email select q;
if (query.Count() > 0)
{
foreach (var updated in query)
{
fmanage.FileName = FileName;
fmanage.Path = path;
session.SaveChanges();
}
}
}
}
else ModelState.AddModelError("", "Remove the errors and try again");
return View();
}
You have a typing error in your path...
Replace...
var path = Path.Combine(Server.MapPath("~/App_Dta/Uploads"), FileName);
With...
var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"), FileName);
You also need to make sure you have the relevant permissions to write to this directory.
Based on your error, the filepath looks incorrect.
c:\users\wasfa\documents\visual studio
2012\Projects\MvcMembership\MvcMembership\App_Data\Uploads\daed3def-df2b-4406-aa‌​9e-c1995190aa6d.image\jpeg
is daed3def-df2b-4406-aa‌​9e-c1995190aa6d.image\jpeg the name of the file?
Try:
[HttpPost]
public ActionResult UploadPic(FileManagement fmanage, HttpPostedFileBase file)
{
string email = User.Identity.Name;
if (file != null && file.ContentLength > 0)
{
var FileName = string.Format("{0}.{1}", Guid.NewGuid(), Path.GetFileName(file.FileName));
var path = Path.Combine(Server.MapPath("~/App_Dta/Uploads"), FileName);
file.SaveAs(path);
using (var session = DocumentStore.OpenSession("RavenMemberShip"))
{
var query = from q in Session.Query<Registration>() where q.Email == email select q;
if (query.Count() > 0)
{
foreach (var updated in query)
{
fmanage.FileName = FileName;
fmanage.Path = path;
session.SaveChanges();
}
}
}
}
else ModelState.AddModelError("", "Remove the errors and try again");
return View();
}
Before file.SaveAs(path), try to check directory exist, if not, create one,
if(CreateFolderIfNeeded(path);
{
file.SaveAs(path);
}
A private function to create directory if needed,
private static bool CreateFolderIfNeeded(string path)
{
bool result = true;
if (!Directory.Exists(path))
{
try
{
Directory.CreateDirectory(path);
}
catch (Exception)
{ result = false; }
}
return result;
Hope this helps.
Check the var FileName = string.Format("{0}.{1}", Guid.NewGuid(), file.ContentType); line in your code.
The file.ContentType will not return the extension of the file you are uploading. It shuold be like daed3def-df2b-4406-aa‌​9e-c1995190aa6d.jpeg instead of daed3def-df2b-4406-aa‌​9e-c1995190aa6d.image\jpeg
find the extension from the uploaded file using substring.
Hope this help

Resources