I have an action method which is working as I expect. Here is the code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,Title,Content,Category,HeaderFilePath")] Blog blog, HttpPostedFileBase upload)
{
if (ModelState.IsValid)
{
if (upload != null && upload.ContentLength > 0)
{
if (blog.HeaderFilePath != string.Empty && blog.HeaderFilePath != null)
{
try
{
System.IO.File.Delete(HttpContext.Server.MapPath("~/") + "images/" + blog.HeaderFilePath);
}
catch (Exception)
{
//TODO: handle it properly
//throw;
}
}
blog.HeaderFilePath = Guid.NewGuid() + ".jpg";
CustomHttpPostedFile f = new CustomHttpPostedFile(upload.InputStream, "jpg", HttpContext.Server.MapPath("~/") + "images/" + blog.HeaderFilePath);
f.SaveAs(HttpContext.Server.MapPath("~/") + "images/" + blog.HeaderFilePath);
}
db.Entry(blog).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(blog);
}
This Action method is doing its job no problem, Am I missing something?
The sign above the method body looks like "0 references | 1 request, 100% failed | 0 exceptions".
When i click on it it doesnt provide me any usefull information.
Edit: here is the screenshot showing no information for the failed request.
Related
public ActionResult UploadImage(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
try
{
string path = Path.Combine(Server.MapPath("~/Images"),
Path.GetFileName(file.FileName));
file.SaveAs(path);
ViewBag.FileStatus = "File uploaded successfully";
}
catch (Exception ex)
{
ViewBag.FileStatus = "ERROR:" + ex.Message.ToString();
}
}
else
{
ViewBag.FileStatus = "You have not specified a file.";
}
return Json("No files selected.", JsonRequestBehavior.AllowGet);
}
Second ActionResult PhysicianBiodata()
public ActionResult PhysicianBiodata (int? Id)
{
PhysicianBiodata newForm = new PhysicianBiodata();
if (Id <= 0 || Id == null)
{
return RedirectToAction("UploadImage", "ServiceCompendium",
{HttpPostedFileBase httpPostedFileBase});
}
else
{
newForm = compendiumData.GetPhysicianBiodatas().Where(x => x.ID == Id)
.FirstOrDefault();
}
return View(newForm);
}
and I want to call this UploadImage() into PhysicianBiodata() but its not working. Can you please help me....
Can you fix the last argument to the redirect?
Something like
return RedirectToAction("UploadImage", "ServiceCompendium", { new #file =httpPostedFileBase});
Also, where is httpPostedFileBase in the PhysicianBiodata method?
Good day Someone.
I am new to asp.net mvc.
I created a simple web application using asp.net mvc.
The application is used to upload image from to a folder. The application works well in visual studio, but once i publish and put on iis it does not upload the image.
I am thinking if there is way to debug the published version so that i can get where the issued is ?
Kindly help on how i can debug the published version and how to solve the problem .
Below is where it is catching the error
string path = System.IO.Path.Combine(targetLocation, file.FileName);
I Would suggest doing the debugging for ASP.NET MVC Application to follow the below points.
Server-side - You should use do exception filter to write any issues to text files and track it
Front - End - the developer tool in the browser level for javascript related things.
DataBase Side - You can use the SQL profiler to use catch the server-side debugging.
add try catch block in your codes
and in the catch code log the exception error message into a file in server to see what is the exact error as following:
add this model to your solution under "Models" folder or anywhere
public class ExceptionLogger
{
private string sLogFormat;
public void ErrorLog(string sErrMsg)
{
try
{
string LogDirectory = "C:\LogFiles\";
CheckCreateLogDirectory(LogDirectory);
LogDirectory = (LogDirectory + "Log_" + DateTime.Now.ToString("dd_MM_yyyy", new CultureInfo("en-us")) + ".txt");
sLogFormat = DateTime.Now.ToString("dd/MM/yyyy", new CultureInfo("en-us")) + " " + DateTime.Now.ToString("HH:mm:ss", new CultureInfo("en-us")) + " ==> ";
StreamWriter sw = new StreamWriter(LogDirectory, true);
sw.WriteLine(sLogFormat + sErrMsg);
sw.Flush();
sw.Close();
}
catch (Exception e) {
}
}
private bool CheckCreateLogDirectory(string LogPath)
{
bool loggingDirectoryExists = false;
DirectoryInfo oDirectoryInfo = new DirectoryInfo(LogPath);
if (oDirectoryInfo.Exists)
{
loggingDirectoryExists = true;
}
else
{
try
{
Directory.CreateDirectory(LogPath);
loggingDirectoryExists = true;
}
catch
{
throw new Exception();
// Logging failure
}
}
return loggingDirectoryExists;
}
}
Then in your controller or repository where errors may happen do the following:
a- add this code in top:
ExceptionLogger Err = new ExceptionLogger();
//you need to write "using" in top to refactor the import error
// something like this: using YourProjectName.Models;
b- in your code blocks add try catch block
try{
//your code
}catch(Exception ex){
Err.ErrorLog(ex.Message + " --- , ---- " + ex.InnerException);
}
another way is to add OnException event on your BaseController which will detect any error or exception, hence you can log it without try-catch blocks, do it as following:
define this in your baseController: ExceptionLogger Err = new ExceptionLogger(); with its using then add the event:
protected override void OnException(ExceptionContext filterContext)
{
var isSent = false;
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
{
return;
}
if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
{
return;
}
if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
{
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
error = true,
message = filterContext.Exception.Message
}
};
LogError("Controller: AjaxCall" + " Action: AjaxCall" + filterContext.Exception.Message, filterContext.Exception);
}
else if (filterContext.Exception is HttpAntiForgeryException)
{
Response.Clear();
Server.ClearError(); //make sure you log the exception first
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { action = "Logout", controller = "Account" }));
}
else
{
var controllerName = (string)filterContext.RouteData.Values["controller"];
var actionName = (string)filterContext.RouteData.Values["action"];
var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
if (actionName == "_Menu")
{
isSent = true;
Response.Redirect("~/Account/Logout");
}
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Error/Error.cshtml",
MasterName = null,
ViewData = new ViewDataDictionary(model),
TempData = filterContext.Controller.TempData
};
////Redirect or return a view, but not both.
LogError("Controller: " + controllerName + " Action: " + actionName + filterContext.Exception.Message, filterContext.Exception);
}
// log the error by using your own method
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.Clear();
if (isSent == false)
{
filterContext.HttpContext.Response.StatusCode = 500;
}
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
private void LogError(string message, Exception exception)
{
Err.ErrorLog(message + " && " + exception.Message);
}
now when errors happen then you will go to c:/logfiles folder in the server and find the exact error happened
I am trying to update the record of an item as follows
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Label,Description,LessonId,Position,FileName,Format,Status")] Content content)
{
if (id != content.Id)
{
return NotFound();
}
var existingContent = await _context.Contents.FindAsync(id).ConfigureAwait(false);
if (existingContent == null)
{
return NotFound();
}
string fileToDelete = null;
if (ModelState.IsValid)
{
try
{
if (Request.Form.Files["FileName"] != null)
{
IFormFile uploadedFile = Request.Form.Files["FileName"];
var lesson_mimetype = uploadedFile.ContentType;
string[] extensions = new string[] { ".jpeg", ".jpg", ".gif", ".png", ".mp4", ".mp3", ".pdf" };
ResponseMsg fileTypeValidationMsg = FileUploadHelper.ValidateFileExtension(uploadedFile, extensions);
if (!fileTypeValidationMsg.ResponseStatus)
{
ModelState.AddModelError("FileName", fileTypeValidationMsg.ResponseDescription);
}
ResponseMsg filesizeValidationMsg = FileUploadHelper.ValidateFilesize(uploadedFile, 200);
if (!filesizeValidationMsg.ResponseStatus)
{
ModelState.AddModelError("FileName", filesizeValidationMsg.ResponseDescription);
}
if (content.Format == ResourceFormat.Text)
{
string desiredUploadDirectory = "TextResources";
string lesson_file_name = await uploadHelper.SaveFileAsync(Request.Form.Files["FileName"], desiredUploadDirectory).ConfigureAwait(false);
existingContent.TextFileUrl = desiredUploadDirectory + "/" + lesson_file_name;
existingContent.FileName = lesson_file_name;
fileToDelete = existingContent.TextFileUrl;
}
else
{
string desiredUploadDirectory = "MultimediaResources";
string lesson_file_name = await uploadHelper.SaveFileAsync(Request.Form.Files["FileName"], desiredUploadDirectory).ConfigureAwait(false);
existingContent.MultiMediaFileUrl = desiredUploadDirectory + "/" + lesson_file_name;
existingContent.FileName = lesson_file_name;
fileToDelete = existingContent.MultiMediaFileUrl;
}
}
existingContent.LastUpdated = DateTime.Now;
existingContent.Label = content.Label;
existingContent.Description = content.Description;
existingContent.LessonId = content.LessonId;
existingContent.Position = content.Position;
existingContent.Status = content.Status;
existingContent.Format = content.Format;
//_context.Update(existingContent); Now removed for the code to work
await _context.SaveChangesAsync().ConfigureAwait(false);
if (fileToDelete != null)
{
System.IO.File.Delete(fileToDelete);
}
return RedirectToAction(nameof(Index));
}
catch (Exception e)
{
ModelState.AddModelError("", e.Message);
}
}
ViewData["LessonId"] = new SelectList(_context.Lessons, "Id", "Label", content.LessonId);
return View(content);
}
But the problem is that when I submit the form for the update, I get the following error message
The instance of entity type 'Content' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
I do not know how to resolve this. I will appreciate any guide please.
In most cases, EF will automatically detect which fields need updating, having an update function in a context (that takes an entity) is a red flag to say you are trying to do something that is not required.
EF does a lot of things behind the scenes, so you don't have to think about them. This is one of them.
I suspect you read a really old blog about how someone 10 years ago had to do something to get EF to update a record.
Also, remove that update function from your context class, so that no-one else trips up on it.
I am sending a Post using ajax for my controller to update the records of a product, but I get the following error:
"The instance of entity type 'Produtos' cannot be tracked because
another instance with the same key value for {'Cod'} is already being
tracked. When attaching existing entities, ensure that only one entity
instance with a given key value is attached. Consider using
'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the
conflicting key values."
my knowledge is still very limited and I do not know what I am doing wrong.
Here is where I load the data on the screen for editing:
[HttpGet]
public PartialViewResult EditaProduto(int cod)
{
var produtos = new Produtos();
if (cod != 0)
produtos = _petalertaContext.Produtos.Where(c => c.Cod == cod).SingleOrDefault();
return PartialView("_ProdutoCadAlt", produtos);
}
Here is where I create or update the product in the database:
[HttpPost]
public IActionResult GravaProduto([FromBody] Produtos produto)
{
if (ModelState.IsValid)
{
try
{
int codShop = Convert.ToInt32(new UserLogado(this.User).PegaDados("cod"));
produto.Codshop = codShop;
Produtos prodAtual = _petalertaContext.Produtos.Find(produto.Cod);
string strResp = "Produto alterado com sucesso!";
if (prodAtual == null)
{
strResp = "Produto adicionado com sucesso!";
prodAtual = _petalertaContext.Produtos.Where(c => c.Nome.ToUpper() == produto.Nome.ToUpper() && c.Codshop == codShop).SingleOrDefault();
if (prodAtual != null)
return Content("Erro: Você já possui o produto " + produto.Nome + " cadastrado!");
_petalertaContext.Add(produto);
}
else
{
_petalertaContext.Update(produto); //<== ERROR
}
_petalertaContext.SaveChanges();
return Content(strResp);
}
catch (DbUpdateConcurrencyException ex)
{
return Content("Erro ao gravar produto: " + ex.Message + " : " + ex.InnerException?.Message);
}
}
return Content("Erro: Não foi possível gravar o produtoes!");
}
Thanks for any help, thank you!
I believe it has to do with this line:
Produtos prodAtual = _petalertaContext.Produtos.Find(produto.Cod);
You already have produto so you don't need to get it again.
I would just do this:
produto.Codshop = codShop;
DbEntityEntry<Produtos> entry = _petalertaContext.Entry(produto);
entry.State = EntityState.Modified;
_petalertaContext.SaveChanges();
So I'm currently building a Web Api with .NET, and using async calls with entity framework.
On my PUT endpoint for a controller, I'm trying to get whether the user already belongs to another level, or if he's in the DB at all, here's the controller code:
[HttpPut]
public async Task<IHttpActionResult> PutCommittee(CommitteeViewModel committee)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (!User.IsInRole("Dean") && !User.IsInRole("Chair"))
return Unauthorized();
var user = await db.Users.Where(u => u.Cn == User.Identity.Name).FirstOrDefaultAsync();
if (user == null) { return BadRequest("Your user does not exist"); }
if (User.IsInRole("Dean"))
{
var college = await db.Colleges.Where(c => c.Dean.Cn == user.Cn).FirstOrDefaultAsync();
if (college == null) { return BadRequest("You're not a Dean of any college"); }
committee.Name = _utils.getCollegeCommitteeName(college);
}
else
{
var department = await db.Departments.Where(d => d.Chair.Cn == user.Cn).FirstOrDefaultAsync();
if (department == null) { return BadRequest("You're not a Chair of any college"); }
committee.Name = _utils.getDepartmentCommitteeName(department);
}
var model = await db.Commitees.Where(c => c.Name == committee.Name).FirstOrDefaultAsync();
if (model == null)
return BadRequest("You have no committee");
var tuple = await getUsers(committee);
model.Users = tuple.Item1;
if (model.Users == null)
return BadRequest(tuple.Item2);
db.Entry(model).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
throw;
}
return StatusCode(HttpStatusCode.NoContent);
}
And Here's the function that checks for the users:
private async Task<Tuple<List<User>, string>> getUsers(CommitteeViewModel committee)
{
string error = "";
List<User> users = new List<User>();
var tuple = new Tuple<List<User>, string>(users, error);
var role = await db.Roles.Where(r => r.Name == "Committee").FirstOrDefaultAsync();
foreach (UserViewModel u in committee.Users)
{
var user = await db.Users.Where(us => us.Cn == u.Cn).FirstOrDefaultAsync();
if (user != null)
{
if (user.Role.Name == "Chair" || user.Role.Name == "Dean")
{
error = "User " + user.Name + " is a " + user.Role.Name + " and cannot be member of a review committee";
return tuple;
}
users.Add(user);
}
else
{
user = _loginProvider.generateUser(u.Cn, role);
db.Users.Add(user);
await db.SaveChangesAsync();
users.Add(user);
}
}
return tuple;
}
I'm using a tuple since async method don't support OUT parameters, in case there's an error.
So the problem is that when I delete a user in my front-end (and then send a put request with the updated array), and I debug step by step, it does delete it, but when I don't, if I put a breakpoint at the try block, the variable model.Users contains the previous array (the original from the model), and this only happens when I delete a user from an array, and the weird thing is that it also happened when I wrote the code synchronously
Thank you for your help.
Just remember... Async methods running back server, so if you have proccess that need run first you need to replace async method for a simple one. Trying it and I´m sure you can solve it.