Using EF5 Code First and Generic Repository/UOW pattern connecting to SQL Server 2008 R2 DB, When entering an invalid server entry in the connection string via app config, an invalid connection exception is not thrown - it runs through the model creating method and nothing happens, I was expecting an exception to be thrown which I can capture and return the information back to the user,
does anyone have any ideas why the exception is not being thrown.
I include code examples below
thanks in advance
Mark
BaseFootballContext which takes in the connection string (if I pass in an invalid string which points to a server I cannot connect to via Query Management Tool
public class BaseFootballContext : DbContext
{
public BaseFootballContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
Configuration.AutoDetectChangesEnabled = false;
}
public IDbSet<Booking> Bookings { get; set; }
// other IDbSets exist
/// <summary>
/// Set Primary Keys and other properties here using Fluent API
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Booking>()
.Property(x => x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Booking>().HasKey(x => x.Id);
modelBuilder.Entity<Booking>().Property(x => x.Version).IsRowVersion();
modelBuilder.Entity<Booking>().Ignore(x => x.IsBrief);
modelBuilder.Entity<Booking>().Property(x => x.ModifiedDate).HasColumnType("datetime2");
modelBuilder.Entity<Booking>().Property(x => x.CreatedDate).HasColumnType("datetime2");
}
}
I have no exception handling higher up the chain, when debugging it goes into the model creating method and just carries on as normal, was expecting a connection exception to be thrown here.
(moving from comment) The process that Mark listed does not trigger database init or a call to the database. He then confirmed that he was executing a query on the context which would, indeed trigger a call to the database and should have thrown an exception to alert him to a problem with the connection string. So the question became one of hunting down the exception which was being "swallowed" by a timeout error. See details about this in the above comments.
Related
I want to create SQL Server DB/tables using EF Model's code first approach.
Here is my simple model class
public class MyApplication
{
[Key]
public string AppID { get; set; }
public string AppName { get; set; }
}
and my DBContext class is shown here
public class PolicyDBContext : DbContext
{
public PolicyDBContext(DbContextOptions options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder OptionaBuilder)
{
if (OptionaBuilder.IsConfigured)
{
OptionaBuilder.UseSqlServer(builder => builder.EnableRetryOnFailure());
}
}
DbSet<MyApplication> AppRoles { get; set; }
}
Here is my config code in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PolicyDBContext>(item => item.UseSqlServer("Server=MyServer;Database=MyDB;user id=testuid;Password=testpwd;");
}
Then I was able to run the "add-migration initialmigration" command successfully
but when I run the "update-database" command, it always fail with the following error
Error Number:64,State:0,Class:20
A transient exception occurred during execution. The operation will be retried after 15024ms.
Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 0 - The specified network name is no longer available.)
After executing "update-database" however, I notice that the new database always get created on my SQL Server, but with no tables in it. I think that indicates that at least my connection string is good.
As you can see from code above, I did EnableRetryOnFailure, as suggested by people in responding to issues similar to mine. But it doesn't solve my problem except that it will retry a few times (6) before finally gives up.
What am I missing here?
There are two approach in the code first option. You should use protected override void OnModelCreating(ModelBuilder modelBuilder)
{ }
You should define configuration in this method.
For more details, visit this link.
Not sure why it works this way but I now know how to fix it. It appears that I need to run update-database command twice. The first time will fail but, as I mentioned in my post, the new empty DB will be created. Now, leave the empty DB there - DO NOT DELETE IT! - and run the update-database command again. This time it will succeed and the tables will be created.
Friends tell me what is the core meaning of init parameter in case of a servlet.
I know that how to initialize it in a web.xml but I don't know what is the actual purpose of it why it is required? Please tell me with a good example.
The Javadoc says: "A convenience method which can be overridden so that there's no need to call super.init(config)."
The init method's main purpose is to allow customization while you are initializing the servlet.
The simplest implementation is when you don't want to do any customization according to your application you can always call super.init method.
To understand meaning of what different init params can be there and how init method is useful:
Imagine a system Of BookManagement system, here for adding books and removing books from db you will be needing Database connection over which you can access the data. Now as Servlet's init method is called for the first request and database connection also needs be created only once(or n number of time if doing connection pooling) then initializing the database connection is something that you should do in init method.
A code snippet from Softlab example , let's assume that getInitParameter method reads the databaseUrl and other properties from web.xml
public class DBServlet ... {
Connection connection = null;
public void init() throws ServletException {
// Open a database connection to prepare for requests
try {
databaseUrl = getInitParameter("databaseUrl");
... // get user and password parameters the same way
connection = DriverManager.getConnection(databaseUrl,
user, password);
} catch(Exception e) {
throw new UnavailableException (this,
"Could not open a connection to the database");
}
}
...
}
One more example of counting the number of time servlet was accessed: https://docstore.mik.ua/orelly/java-ent/servlet/ch03_03.htm
So in Summary: To do customization like read the initial values of variable or to initialize resources(like db connection) you can use init method.
Below is the source code of init methods :
public void init(ServletConfig config)throws ServletException
{
this.config = config;
int();
}
public void init() throws ServletException;
It is recommended to override to init() method, not init(ServletConfig).
When overriding init(ServletConfig), the first thing that must be done is to call:
super.init(config);
If you do this then calling directly to getServletContext() in your method will no longer result in an NPE.
I've developed a sample SignalR application based on ASP.NET 4.5 & Owin, and I've hosted that app on IIS 7.5.
Everything is working fine, but how can I handle exceptions in Owin?
Consider the following code:
[HubName("SampleHub")]
public class SampleHub : Hub
{
public SampleHub()
{
throw new InvalidOperationException("?!");
}
}
This exception won't call Application_Error (and this is my problem).
Where can I get all exceptions from Owin for logging and debugging purposes similarly to Application_Error?
I'm not interested in something like this:
app.UseErrorPage(new ErrorPageOptions()
{
ShowCookies = true,
ShowEnvironment = true,
ShowExceptionDetails = true,
ShowHeaders = true,
ShowQuery = true,
ShowSourceCode = true
});
This is totally useless for advanced scenarios, something like ASP.NET Web API and ASP.NET MVC.
Action filters with OnException method for override purposes is much better.
If you want exception handling specifically for SignalR Hubs, OWIN middleware is not the way to go.
To illustrate just one reason why, suppose that SignalR is using its WebSocket transport when an exception is thrown from inside a Hub method. In this case, SignalR will not close the WebSocket connection. Instead SignalR will write a JSON encoded message directly to the socket to indicate to the client that an exception was thrown. There is no easy way using OWIN middleware to trigger any sort of event when this happens outside of possibly wrapping the entire OWIN WebSocket Extension which I would strongly advise against.
Fortunately SignalR provides its own Hub Pipeline which is perfectly suited for your scenario.
using System;
using System.Diagnostics;
using Microsoft.AspNet.SignalR.Hubs;
public class MyErrorModule : HubPipelineModule
{
protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext)
{
MethodDescriptor method = invokerContext.MethodDescriptor;
Debug.WriteLine("{0}.{1}({2}) threw the following uncaught exception: {3}",
method.Hub.Name,
method.Name,
String.Join(", ", invokerContext.Args),
exceptionContext.Error);
}
}
You can use the ExceptionContext for more than just logging. For example you can set ExceptionContext.Error to a different exception which will change the exception the client receives.
You can even suppress the exception by setting ExceptionContext.Error to null or by setting ExceptonContext.Result. If you do this, It will appear to the client that the Hub method returned the value you found in ExceptonContext.Result instead of throwing.
A while back a wrote another SO answer about how you can call a single client callback for every exception thrown by a Hub method: SignalR exception logging?
There is also MSDN documentation for HubPipelineModules: http://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.hubs.hubpipelinemodule(v=vs.118).aspx
The answer by #halter73 is great for errors thrown inside hubs, but it doesn't catch errors thrown during their creation.
I was getting the exception:
System.InvalidOperationException: 'foobarhub' Hub could not be resolved.
The server was returning an HTML page for this exception, but I needed it in JSON format for better integration with my Angular app, so based on this answer I implemented an OwinMiddleware to catch exceptions and change the output format. You could use this for logging errors instead.
public class GlobalExceptionMiddleware : OwinMiddleware
{
public GlobalExceptionMiddleware(OwinMiddleware next)
: base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
try
{
await Next.Invoke(context);
}
catch (Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = 500;
await context.Response.WriteAsync(JsonConvert.SerializeObject(ex));
}
}
}
Add the registration in OwinStartup.cs, just remember to place it before the MapSignalR method call:
public class OwinStartup
{
public void Configuration(IAppBuilder app)
{
app.Use<GlobalExceptionMiddleware>(); // must come before MapSignalR()
app.MapSignalR();
}
}
I have an ASP.NET Web Forms application with UI, Service layer and Repository layer.
Some of the methods in my Service Layer communicates with a Web Service, therefore I would like to wrap all the calls to the Web Methods in a Try-Catch-Finally construct.
Suppose I have the following methods in my Service Layer:
public RegistrationDetails GetRegistrationDetails(int userId)
public bool RegisterUser(UserData myUserData)
Where RegistrationDetails and myUserData are object types (classes).
My concern is the following: if I create a Try-Catch-Finally to wrap the call to the Web Service within the implementation of the methods listed above, in case there is an exception how can I return the message string if the return types are RegistrationDetails and bool?
I was thinking about adding a property to every return object but I do not know if that is a good solution. For instance instead of using bool:
public class RegisterResponse
{
public bool isRegistered { get; set; }
public string ExceptionMessage { get; set; }
}
public RegisterResponse RegisterUser(UserData myUserData)
And then check if ExceptionMessage is null or String.Empty. Is it a good approach? Thanks
1) As mentioned by IrishChieftain, bubbling the exception down to the forms is good, you will be able to respond to the exception better
2) You can also have a reference parameter as array which stores exception messages generated from the method
public bool RegisterUser(UserData myUserData, optional ref ArrayList<string> errors)
{
if(error)
errors.Add("This error occured")
}
3) For Instance Object, you could have an Instance variable of ArrayList for errors and have that returned in a property
public class MyClass
{
private ArrayList<string> errors = new ArrayList<string>
public ArrayList<string> ExceptionMessages()
{
get
{
return errors;
}
}
public RegistrationDetails GetRegistrationDetails(int userId) { }
}
//Used like this:
MyClass c = new MyClass();
c.GetRegistrationDetails();
if(c.ExceptionMessages > 0)
{
//output errors
}
But I would prefer the first approach - for flexibility like output formatting
Passing raw exceptions on to your client (web forms layer) from a service could be risky. If it's a database exception, it might expose details of your database. A malicious user might call your service layer methods from their own application.
You can expect two types of exceptions on the client level:
Communication Exception (problems connecting to the service)
Server-side error (database problem, username not unique, password invalid... other business rule exceptions)
The first type should be caught in try-catch-finally in your web forms layer, but the second kind should be caught in the service layer, logged, then wrapped up in the RegisterResponse object, as you suggest. But, instead of sending Exception.Message, you might consider using an enum of expected errors (with a ServerError member to cover anything else.) You could also add an EventId to the response and log entry so that you can investigate errors.
public enum RegisterResponseError { NoError = 0, SystemError = 1,
UserNameNotUnique, PasswordInvalid, etc. }
public class RegisterResponse
{
public bool isRegistered { get; set; }
public RegisterResponseError ErrorCode { get; set; }
}
Then in your client code,
if(myRegisterResponse.ErrorCode == RegisterResponseError.NoError)
// everything was fine
else
// show a suitable error message for ErrorCode and display EventId (if logging)
You could return an error string from your service, but it's probably better to manage any content in your web forms layer, in case you need to localize the content or use a CMS later on.
I'm migrating some servlets over to the Spring framework, using Spring MVC. Currently in each servlet we authenticate the user and if the authentication fails we do this:
if (authfailed)
{
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"You are not authorized.");
return;
}
On the front end is a YUI-based application, and when an error status is returned the "failure" callback displays a dialog with the error message given above.
I know in my controller I can get the response object and call sendError, but is that the best way to handle this? sendError also throws an IOException so I'd have to catch that - a bit of annoying code to insert in every method of every controller.
I have the same problem handling exceptions - the servlets have try-catch blocks that call sendError in the catch method. I know I can mark my exception handlers with
#ExceptionHandler
#ResponseStatus(value = HttpStatus.NOT_FOUND)
but doesn't the exception handling class need to be in each controller class?
Finally, if the exception happens in a service called from a controller, does the exception bubble up to the controller or should I handle the exception in the service (thus pushing these exception handling issues into the service layer)?
This seems more difficult than it should be, but as with many things in Spring it's likely I don't understand what's going on. All I want to do is to send an error status and message back in the response!
Thanks,
Paul
It looks like you have the most of the answers in your question itself :)
To reiterate,
Have the controller like this
#RequestMapping("/test")
public String verifyAuth(HttpServletRequest request) throws NotFoundException {
String id = request.getParameter("id");
if (id == null)
throw new NotFoundException("Id not found in the request");
return "success";
}
Declare the exception class in NotFoundException.java,
#ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Id Not Found")
public class NotFoundException extends Exception {
public NotFoundException(String msg) {
super(msg);
}
}
This exception class need not be every controller class. Declare it as public class and import it in every required controller.
This is one way of doing it. If you like the non-spring style, declare HttpServletResponse in every controller arguments and do
#RequestMapping("/test")
public String verifyAuth(HttpServletRequest request, HttpServletResponse response) {
...
try {
response.sendError(..)
catch(..) {}
}
Or you can use views to show error message,
#RequestMapping("/test")
public String verifyAuth(HttpServletRequest request, Map<String, Object> map){
String id = request.getParameter("id");
if (id == null) {
map.put("status", HttpStatus.NOTFOUND);
map.put("reason", "Id Not Found");
return "error"
}
return "success";
}
Make sure your viewResolver is configured correctly and in the error.jsp to get the error string, you could say.
<body>
${status} ${reason}
</body>
Define error.jsp with nice css for all kind of errors you would expect.
These are not the only ways. With spring you have freedom to do anything. I have seen few ppl rendering json object for error message.
To answer your another question of if the error happens in the service called by the controller is depend on your scenario. For example you are trying to read the user store, if the user store not available error happens, I would handle there itself to read from another replica user store if one available and If I found user does not exist I would leave the exception to the controller to throw.