Answered by:
ASP.Net EntityFramework SaveChanges central

Question
-
Hey
I have a question relating to ASP.NET (MVC) and EntityFramework
This is my first ASP.NET application I am writing, in the past I wrote for WinForms. - There I always had a central "Shared" class, which I called, when there was data to save.
Now, in ASP.NET, I read, that Shared shouldn't be used, because you never can say, who is calling it. (Makes sense for me)
But, has anybody of you a way, to manage the Try/Catch, Error handling and logging in a central class with ASP.NET?
I don't want to write each time, when I save data:
Using myBaseDataContext As New Base.BaseDataContext myDataContext.Database.Log = AddressOf myLogging.LogDatabase Try myDataContext.SaveChanges() Catch ex as Exception myLogging.LogException(ex) ' Give back the error to the user End Catch End Using
This would be redundant Code, and we all know, that we shouldn't do that .... ;)
THX a lot
Friday, April 8, 2016 3:23 PM
Answers
-
In an WinForms program I can create a "Shared" class, which can be reached from everywhere in the Code. And there I check, if an error occurs, I log the changes and so on.
I suggest that you understand an Abstract base class that's like in the C# example of a MVC controller that inherits from the BaseController. It's the BaseController that has the single try/catch and logging using Log4net.
In your case, you would have a BasePage that all Webpages inherit from the BasePage that inherits from WebPage.
Of course, you could use the same approach in Windows forms based solution too.
The MVC controller like a ASP.NET UI Web form or even a Window UI form is the highest point in the solution. So, you have a single try/catch in the base class and exceptions thrown below the base class bubble up to the base class where they are caught. You don't need try/catches all of over the place, just the single try/catch at the highest point and let the exception bubble up to the base class and log the exception.
namespace CEEPRebatePortal.Controllers { public abstract class BaseWebController : Controller { #region "Dependencies" public ILogger Logger { get; set; } #endregion /// <summary> /// Handle errors by showing error page and redirecting to Error page /// </summary> /// <param name="filterContext"></param> protected override void OnException(ExceptionContext filterContext) { // see if we need to find the "Real Exception" Exception actualException = filterContext.Exception; while ( ((actualException is HttpException) || (actualException is HttpUnhandledException)) && (actualException.InnerException != null) ) { actualException = actualException.InnerException; } if (Logger != null) { // Logger should always be non-null, but don't risk it Logger.Error(string.Format( "Exception on request \"{0}\" with referrer \"{1}\"", Request.Url, Request.UrlReferrer), actualException); // For database validation exceptions, report details if (actualException is DbEntityValidationException) { foreach (var err in ((DbEntityValidationException)actualException).EntityValidationErrors.SelectMany(errs => errs.ValidationErrors)) { Logger.Error(string.Format("Validation failed on property {0}: {1}", err.PropertyName, err.ErrorMessage)); } } } // base exception handler will redirect us to Error page, depending on CustomErrors setting in web.config base.OnException(filterContext); } } }
namespace CEEPRebatePortal.Controllers { [Authorize(Roles="Submitter")] public class RebateWizardController : BaseWebController { #region "Dependencies" public IRequestsDalMgr requestsDalMgr { get; set; } #endregion private const string ADDMODELSESSIONKEY = "addmodel"; private const string ERRORMESSAGE = "Please fix the following errors:"; [HttpGet] public ActionResult Index()
- Marked as answer by Zero-G. _ Saturday, April 9, 2016 1:23 PM
Saturday, April 9, 2016 10:53 AM
All replies
-
Hello,
Have you considered asking your question in the ASP.NET Forums.
Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
VB Forums - moderator
- Proposed as answer by Cor Ligthert Friday, April 8, 2016 5:45 PM
Friday, April 8, 2016 5:35 PM -
I don't see what is wrong with your approach, the error is logged on the server, exactly where it should be.
However, the knowledge about ASP.Net has declined in this forum, therefore it is better to follow the advice of Karen.
Success
CorFriday, April 8, 2016 5:45 PM -
But, has anybody of you a way, to manage the Try/Catch, Error handling and logging in a central class with ASP.NET?
No one would do what you are doing in an ASP.NET solution. They would use a logging tool like Log4net. If the DB goes down, then what are you going to do?
http://www.codeproject.com/Articles/42276/How-to-Use-Log-Net-with-VB-NET-A-Simple-Step-By-St
Friday, April 8, 2016 9:20 PM -
Override the SaveChanges method of the generated context with your own partial class and then you can execute your logging logic from within the context, regardless of where or when the context is used.
Reed Kimble - "When you do things right, people won't be sure you've done anything at all"
Friday, April 8, 2016 10:03 PM -
Hey
First of all, thanks for your Reply
Second, I will ask my question in ASP.NET again
Third. I think there was a missunderstanding of my question
I asked about central saving. The logging was just to clarify, that there will be a big amount of Code, which is redundant everytime a "SaveChanges" is called.
@DA924x -> I use a professional logging tool and there it will be done, like in the Code I have posted.
But this doesn't matter at all.
Again, I try to clarify:
In an WinForms program I can create a "Shared" class, which can be reached from everywhere in the Code. And there I check, if an error occurs, I log the changes and so on.
The question was, how to solve something like this in an ASP.NET application.
THX
Saturday, April 9, 2016 9:22 AM -
In an WinForms program I can create a "Shared" class, which can be reached from everywhere in the Code. And there I check, if an error occurs, I log the changes and so on.
I suggest that you understand an Abstract base class that's like in the C# example of a MVC controller that inherits from the BaseController. It's the BaseController that has the single try/catch and logging using Log4net.
In your case, you would have a BasePage that all Webpages inherit from the BasePage that inherits from WebPage.
Of course, you could use the same approach in Windows forms based solution too.
The MVC controller like a ASP.NET UI Web form or even a Window UI form is the highest point in the solution. So, you have a single try/catch in the base class and exceptions thrown below the base class bubble up to the base class where they are caught. You don't need try/catches all of over the place, just the single try/catch at the highest point and let the exception bubble up to the base class and log the exception.
namespace CEEPRebatePortal.Controllers { public abstract class BaseWebController : Controller { #region "Dependencies" public ILogger Logger { get; set; } #endregion /// <summary> /// Handle errors by showing error page and redirecting to Error page /// </summary> /// <param name="filterContext"></param> protected override void OnException(ExceptionContext filterContext) { // see if we need to find the "Real Exception" Exception actualException = filterContext.Exception; while ( ((actualException is HttpException) || (actualException is HttpUnhandledException)) && (actualException.InnerException != null) ) { actualException = actualException.InnerException; } if (Logger != null) { // Logger should always be non-null, but don't risk it Logger.Error(string.Format( "Exception on request \"{0}\" with referrer \"{1}\"", Request.Url, Request.UrlReferrer), actualException); // For database validation exceptions, report details if (actualException is DbEntityValidationException) { foreach (var err in ((DbEntityValidationException)actualException).EntityValidationErrors.SelectMany(errs => errs.ValidationErrors)) { Logger.Error(string.Format("Validation failed on property {0}: {1}", err.PropertyName, err.ErrorMessage)); } } } // base exception handler will redirect us to Error page, depending on CustomErrors setting in web.config base.OnException(filterContext); } } }
namespace CEEPRebatePortal.Controllers { [Authorize(Roles="Submitter")] public class RebateWizardController : BaseWebController { #region "Dependencies" public IRequestsDalMgr requestsDalMgr { get; set; } #endregion private const string ADDMODELSESSIONKEY = "addmodel"; private const string ERRORMESSAGE = "Please fix the following errors:"; [HttpGet] public ActionResult Index()
- Marked as answer by Zero-G. _ Saturday, April 9, 2016 1:23 PM
Saturday, April 9, 2016 10:53 AM -
Hey DA924x
THX for this aproach.
I will give it a try
Saturday, April 9, 2016 1:23 PM