Просмотр исходного кода

Added handler event for request errors

Kenric Nugteren 2 лет назад
Родитель
Сommit
ecb3bd4da2

+ 14 - 14
InABox.Client.Remote.Shared/RemoteClient.cs

@@ -170,7 +170,7 @@ namespace InABox.Clients
                 }
                 else if(response.Status == StatusCode.BadServer)
                 {
-                    throw new RemoteException(response.Messages);
+                    throw new RemoteException(response.Messages, request);
                 }
 
             return new ValidationData(
@@ -207,8 +207,8 @@ namespace InABox.Clients
                 return response.Status switch
                 {
                     StatusCode.OK => response.Items,
-                    StatusCode.Unauthenticated => throw new RemoteException("Client not authenticated", StatusCode.Unauthenticated),
-                    _ => throw new RemoteException(response.Messages),
+                    StatusCode.Unauthenticated => throw new RemoteException("Client not authenticated", StatusCode.Unauthenticated, request),
+                    _ => throw new RemoteException(response.Messages, request),
                 };
             }
 
@@ -267,8 +267,8 @@ namespace InABox.Clients
                 return response.Status switch
                 {
                     StatusCode.OK => response.Tables,
-                    StatusCode.Unauthenticated => throw new RemoteException("Client not authenticated"),
-                    _ => throw new RemoteException(response.Messages),
+                    StatusCode.Unauthenticated => throw new RemoteException("Client not authenticated", request),
+                    _ => throw new RemoteException(response.Messages, request),
                 };
             }
 
@@ -304,9 +304,9 @@ namespace InABox.Clients
                     entity.SetObserving(true);
                     break;
                 case StatusCode.Unauthenticated:
-                    throw new RemoteException("Client not authenticated");
+                    throw new RemoteException("Client not authenticated", request);
                 default:
-                    throw new RemoteException(response.Messages);
+                    throw new RemoteException(response.Messages, request);
             }
         }
 
@@ -339,9 +339,9 @@ namespace InABox.Clients
                     }
                     break;
                 case StatusCode.Unauthenticated:
-                    throw new RemoteException("Client not authenticated");
+                    throw new RemoteException("Client not authenticated", request);
                 default:
-                    throw new RemoteException(response.Messages);
+                    throw new RemoteException(response.Messages, request);
             }
         }
 
@@ -362,9 +362,9 @@ namespace InABox.Clients
                 case StatusCode.OK:
                     break;
                 case StatusCode.Unauthenticated:
-                    throw new RemoteException("Client not authenticated");
+                    throw new RemoteException("Client not authenticated", request);
                 default:
-                    throw new RemoteException(response.Messages);
+                    throw new RemoteException(response.Messages, request);
             }
         }
 
@@ -383,9 +383,9 @@ namespace InABox.Clients
                 case StatusCode.OK:
                     break;
                 case StatusCode.Unauthenticated:
-                    throw new RemoteException("Client not authenticated");
+                    throw new RemoteException("Client not authenticated", request);
                 default:
-                    throw new RemoteException(response.Messages);
+                    throw new RemoteException(response.Messages, request);
             }
         }
 
@@ -406,7 +406,7 @@ namespace InABox.Clients
                 {
                     StatusCode.OK => response.Valid,
                     StatusCode.Unauthenticated => false,
-                    _ => throw new RemoteException(response.Messages),
+                    _ => throw new RemoteException(response.Messages, request),
                 };
             }
 

+ 4 - 11
InABox.Client.Remote.Shared/RemoteException.cs

@@ -3,21 +3,14 @@ using System.Collections.Generic;
 
 namespace InABox.Clients
 {
-    public class RemoteException : Exception
+    public class RemoteException : RequestException
     {
-        public StatusCode? Status;
-
-        public RemoteException(IEnumerable<string> messages) : base(string.Join("\n", messages))
+        public RemoteException(IEnumerable<string> messages, Request request) : base(string.Join("\n", messages), StatusCode.Error, request)
         {
         }
 
-        public RemoteException(string message) : base(message)
-        {
-        }
+        public RemoteException(string message, Request request) : base(message, StatusCode.Error, request) { }
 
-        public RemoteException(string message, StatusCode statusCode) : base(message)
-        {
-            Status = statusCode;
-        }
+        public RemoteException(string message, StatusCode statusCode, Request request) : base(message, statusCode, request) { }
     }
 }

+ 265 - 83
InABox.Core/Client/Client.cs

@@ -41,67 +41,133 @@ namespace InABox.Clients
 
         public static Dictionary<string, CoreTable> QueryMultiple(Dictionary<string, IQueryDef> queries)
         {
-            using (var timer = new Profiler(false))
+            try
             {
+                using var timer = new Profiler(false);
                 var result = CheckClient().QueryMultiple(queries);
                 timer.Log(result.Sum(x => x.Value.Rows.Count));
                 return result;
             }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static QueryMultipleResults QueryMultiple(params IKeyedQueryDef[] queries)
         {
-            using (var timer = new Profiler(false))
+            try
             {
+                using var timer = new Profiler(false);
                 var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef));
                 timer.Log(result.Sum(x => x.Value.Rows.Count));
                 return new QueryMultipleResults(result);
             }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
         public static QueryMultipleResults QueryMultiple(IEnumerable<IKeyedQueryDef> queries)
         {
-            using (var timer = new Profiler(false))
+            try
             {
+                using var timer = new Profiler(false);
                 var result = CheckClient().QueryMultiple(queries.ToDictionary(x => x.Key, x => x as IQueryDef));
                 timer.Log(result.Sum(x => x.Value.Rows.Count));
                 return new QueryMultipleResults(result);
             }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static ValidationData Validate(Guid session)
         {
-            using (new Profiler(true))
-                return CheckClient().Validate(session);
+            try
+            {
+                using (new Profiler(true))
+                    return CheckClient().Validate(session);
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static ValidationData Validate(string pin, Guid session = default)
         {
-            using (new Profiler(true))
-                return CheckClient().Validate(pin, session);
+            try
+            {
+                using (new Profiler(true))
+                    return CheckClient().Validate(pin, session);
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static ValidationData Validate(string userid, string password, Guid session = default)
         {
-            using (new Profiler(true))
-                return CheckClient().Validate(userid, password, session);
+            try
+            {
+                using (new Profiler(true))
+                    return CheckClient().Validate(userid, password, session);
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static bool Check2FA(string code, Guid? session = null)
         {
-            using (new Profiler(true))
-                return CheckClient().Check2FA(code, session);
+            try
+            {
+                using (new Profiler(true))
+                    return CheckClient().Check2FA(code, session);
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static bool Ping()
         {
-            using (new Profiler(true))
-                return CheckClient().Ping();
+            try
+            {
+                using (new Profiler(true))
+                    return CheckClient().Ping();
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static DatabaseInfo Info()
         {
-            using (new Profiler(true))
-                return CheckClient().Info();
+            try
+            {
+                using (new Profiler(true))
+                    return CheckClient().Info();
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public static Client Create(Type TEntity) => 
@@ -141,12 +207,20 @@ namespace InABox.Clients
 
         public CoreTable Query(Filter<TEntity>? filter = null, Columns<TEntity>? columns = null, SortOrder<TEntity>? orderby = null)
         {
-            using (var timer = new Profiler<TEntity>(false))
+            try
             {
-                CheckSupported();
-                var result = _client.Query(filter, columns, orderby);
-                timer.Log(result.Rows.Count);
-                return result;
+                using (var timer = new Profiler<TEntity>(false))
+                {
+                    CheckSupported();
+                    var result = _client.Query(filter, columns, orderby);
+                    timer.Log(result.Rows.Count);
+                    return result;
+                }
+            }
+            catch(RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
             }
         }
         public override CoreTable Query(IFilter? filter, IColumns? columns, ISortOrder? sortOrder)
@@ -156,143 +230,251 @@ namespace InABox.Clients
 
         public void Query(Filter<TEntity>? filter, Columns<TEntity>? columns, SortOrder<TEntity>? sort, Action<CoreTable?, Exception?> callback)
         {
-            var timer = new Profiler<TEntity>(false);
-            CheckSupported();
-            _client.Query(filter, columns, sort, (c, e) =>
+            try
             {
-                timer.Dispose(c != null ? c.Rows.Count : -1);
-                callback?.Invoke(c, e);
-            });
-
+                var timer = new Profiler<TEntity>(false);
+                CheckSupported();
+                _client.Query(filter, columns, sort, (c, e) =>
+                {
+                    timer.Dispose(c != null ? c.Rows.Count : -1);
+                    callback?.Invoke(c, e);
+                });
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public TEntity[] Load(Filter<TEntity>? filter = null, SortOrder<TEntity>? sort = null)
         {
-            using (var timer = new Profiler<TEntity>(false))
+            try
             {
-                CheckSupported();
-                var result = _client.Load(filter, sort);
-                foreach (var entity in result)
-                    entity.CommitChanges();
-                timer.Log(result.Length);
-                return result;
+
+                using (var timer = new Profiler<TEntity>(false))
+                {
+                    CheckSupported();
+                    var result = _client.Load(filter, sort);
+                    foreach (var entity in result)
+                        entity.CommitChanges();
+                    timer.Log(result.Length);
+                    return result;
+                }
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
             }
         }
 
         public void Load(Filter<TEntity> filter, SortOrder<TEntity> sort, Action<TEntity[]?, Exception?> callback)
         {
-            var timer = new Profiler<TEntity>(false);
-            CheckSupported();
-            _client.Load(filter, sort, (i,e) =>
+            try
             {
-                timer.Dispose(i != null ? i.Length : -1);
-                callback?.Invoke(i, e);
-            });
-
+                var timer = new Profiler<TEntity>(false);
+                CheckSupported();
+                _client.Load(filter, sort, (i, e) =>
+                {
+                    timer.Dispose(i != null ? i.Length : -1);
+                    callback?.Invoke(i, e);
+                });
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public override void Save(Entity entity, string auditNote)
         {
-            Save((entity as TEntity)!, auditNote);
+            try
+            {
+                Save((entity as TEntity)!, auditNote);
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
         public void Save(TEntity entity, string auditnote)
         {
-            using (new Profiler<TEntity>(true))
+            try
             {
-                CheckSupported();
-                entity.LastUpdate = DateTime.Now;
-                entity.LastUpdateBy = ClientFactory.UserID;
-                _client.Save(entity, auditnote);
-                entity.CommitChanges();
+
+                using (new Profiler<TEntity>(true))
+                {
+                    CheckSupported();
+                    entity.LastUpdate = DateTime.Now;
+                    entity.LastUpdateBy = ClientFactory.UserID;
+                    _client.Save(entity, auditnote);
+                    entity.CommitChanges();
+                }
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
             }
         }
 
         public void Save(TEntity entity, string auditnote, Action<TEntity, Exception?> callback)
         {
-            var timer = new Profiler<TEntity>(false);
-            CheckSupported();
-            _client.Save(entity, auditnote, (i,c) =>
+            try
             {
-                timer.Dispose();
-                callback?.Invoke(i, c);
-            });
+                var timer = new Profiler<TEntity>(false);
+                CheckSupported();
+                _client.Save(entity, auditnote, (i, c) =>
+                {
+                    timer.Dispose();
+                    callback?.Invoke(i, c);
+                });
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public void Save(IEnumerable<TEntity> entities, string auditnote)
         {
-            using (var timer = new Profiler<TEntity>(false))
+            try
             {
+                using var timer = new Profiler<TEntity>(false);
                 CheckSupported();
                 if (entities.Any())
                     _client.Save(entities, auditnote);
                 timer.Log(entities.Count());
             }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public void Save(IEnumerable<TEntity> entities, string auditnote, Action<IEnumerable<TEntity>, Exception?> callback)
         {
-            var timer = new Profiler<TEntity>(false);
-            CheckSupported();
-            if (entities.Any())
-                _client.Save(entities, auditnote, (i,e) =>
-                {
-                    timer.Dispose(i.Count());
-                    callback?.Invoke(i,e);
-                });
+            try
+            {
+                var timer = new Profiler<TEntity>(false);
+                CheckSupported();
+                if (entities.Any())
+                    _client.Save(entities, auditnote, (i, e) =>
+                    {
+                        timer.Dispose(i.Count());
+                        callback?.Invoke(i, e);
+                    });
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
 
         public void Delete(TEntity entity, string auditnote)
         {
-            using (new Profiler<TEntity>(true))
+            try
             {
-                CheckSupported();
-                _client.Delete(entity, auditnote);
+                using (new Profiler<TEntity>(true))
+                {
+                    CheckSupported();
+                    _client.Delete(entity, auditnote);
+                }
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
             }
         }
 
         public void Delete(TEntity entity, string auditnote, Action<TEntity, Exception?> callback)
         {
-            var timer = new Profiler<TEntity>(true);
-            CheckSupported();
-            _client.Delete(entity, auditnote, (i,e) =>
+            try
             {
-                timer.Dispose();
-                callback?.Invoke(i, e);
-            });
+                var timer = new Profiler<TEntity>(true);
+                CheckSupported();
+                _client.Delete(entity, auditnote, (i, e) =>
+                {
+                    timer.Dispose();
+                    callback?.Invoke(i, e);
+                });
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public void Delete(IList<TEntity> entities, string auditnote)
         {
-            using (var timer = new Profiler<TEntity>(false))
+            try
             {
+                using var timer = new Profiler<TEntity>(false);
                 CheckSupported();
                 _client.Delete(entities, auditnote);
                 timer.Log(entities.Count());
             }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public void Delete(IList<TEntity> entities, string auditnote, Action<IList<TEntity>, Exception?> callback)
         {
-            var timer = new Profiler<TEntity>(false);
-            CheckSupported();
-            _client.Delete(entities, auditnote, (i,e) =>
+            try
             {
-                timer.Dispose(entities.Count());
-                callback?.Invoke(i,e);
-            });
+                var timer = new Profiler<TEntity>(false);
+                CheckSupported();
+                _client.Delete(entities, auditnote, (i, e) =>
+                {
+                    timer.Dispose(entities.Count());
+                    callback?.Invoke(i, e);
+                });
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public IEnumerable<string> SupportedTypes()
         {
-            using (new Profiler(true))
-                return _client.SupportedTypes();
+            try
+            {
+                using (new Profiler(true))
+                    return _client.SupportedTypes();
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
 
         public new DatabaseInfo Info()
         {
-            using (new Profiler(true))
-                return _client.Info();
+            try
+            {
+                using (new Profiler(true))
+                    return _client.Info();
+            }
+            catch (RequestException e)
+            {
+                ClientFactory.RaiseRequestError(e);
+                throw;
+            }
         }
     }
 }

+ 9 - 0
InABox.Core/Client/ClientFactory.cs

@@ -57,6 +57,15 @@ namespace InABox.Clients
         
         public static Notifications Notifications { get; set; } = new Notifications();
 
+        public delegate void RequestErrorHandler(RequestException e);
+
+        public static event RequestErrorHandler? OnRequestError;
+
+        public static void RaiseRequestError(RequestException e)
+        {
+            OnRequestError?.Invoke(e);
+        }
+
         private static bool IsSupported(Type t)
         {
             return true;

+ 61 - 7
InABox.Core/Client/Request.cs

@@ -29,6 +29,8 @@ namespace InABox.Clients
         public static Action<Request>? BeforeRequest { get; set; }
 
         public Credentials Credentials { get; set; }
+
+        public abstract RequestMethod GetMethod();
     }
 
     public enum StatusCode
@@ -40,6 +42,21 @@ namespace InABox.Clients
         BadServer
     }
 
+    public enum RequestMethod
+    {
+        Info,
+        Ping,
+        Check2FA,
+        Validate,
+        MultiQuery,
+        MultiDelete,
+        Delete,
+        Save,
+        MultiSave,
+        Query,
+        Notify
+    }
+
     public abstract class Response
     {
         public Response()
@@ -62,19 +79,21 @@ namespace InABox.Clients
     {
     }
 
-    public class ListRequest<TEntity> : BaseRequest<TEntity> where TEntity : Entity, new()
+    /*public class ListRequest<TEntity> : BaseRequest<TEntity> where TEntity : Entity, new()
     {
         public Filter<TEntity>? Filter { get; set; }
 
         public Columns<TEntity>? Columns { get; set; }
 
         public SortOrder<TEntity>? Sort { get; set; }
-    }
 
+        public override RequestMethod GetMethod() => RequestMethod.Query;
+    }
+    
     public class ListResponse<TEntity> : BaseResponse<TEntity> where TEntity : Entity, new()
     {
         public IEnumerable<object[]> Data { get; set; }
-    }
+    }*/
 
     public class QueryRequest<TEntity> : BaseRequest<TEntity> where TEntity : Entity, new()
     {
@@ -83,6 +102,8 @@ namespace InABox.Clients
         public Columns<TEntity>? Columns { get; set; }
 
         public SortOrder<TEntity>? Sort { get; set; }
+
+        public override RequestMethod GetMethod() => RequestMethod.Query;
     }
 
     public class QueryResponse<TEntity> : BaseResponse<TEntity> where TEntity : Entity, new()
@@ -90,7 +111,7 @@ namespace InABox.Clients
         public CoreTable? Items { get; set; }
     }
 
-    public class LoadRequest<TEntity> : BaseRequest<TEntity> where TEntity : Entity, new()
+    /*public class LoadRequest<TEntity> : BaseRequest<TEntity> where TEntity : Entity, new()
     {
         public Filter<TEntity>? Filter { get; set; }
 
@@ -100,12 +121,14 @@ namespace InABox.Clients
     public class LoadResponse<TEntity> : BaseResponse<TEntity> where TEntity : Entity, new()
     {
         public TEntity[] Items { get; set; }
-    }
+    }*/
 
     public class MultiSaveRequest<TEntity> : BaseRequest<TEntity> where TEntity : Entity, new()
     {
         public TEntity[] Items { get; set; }
         public string AuditNote { get; set; }
+
+        public override RequestMethod GetMethod() => RequestMethod.MultiSave;
     }
 
     public class MultiSaveResponse<TEntity> : BaseResponse<TEntity> where TEntity : Entity, new()
@@ -118,6 +141,8 @@ namespace InABox.Clients
     {
         public TEntity Item { get; set; }
         public string AuditNote { get; set; }
+
+        public override RequestMethod GetMethod() => RequestMethod.Save;
     }
 
     public class SaveResponse<TEntity> : BaseResponse<TEntity> where TEntity : Entity, new()
@@ -130,6 +155,8 @@ namespace InABox.Clients
     {
         public TEntity Item { get; set; }
         public string AuditNote { get; set; }
+
+        public override RequestMethod GetMethod() => RequestMethod.Delete;
     }
 
     public class DeleteResponse<TEntity> : BaseResponse<TEntity> where TEntity : Entity, new()
@@ -140,6 +167,8 @@ namespace InABox.Clients
     {
         public TEntity[] Items { get; set; }
         public string AuditNote { get; set; }
+
+        public override RequestMethod GetMethod() => RequestMethod.MultiDelete;
     }
 
     public class MultiDeleteResponse<TEntity> : BaseResponse<TEntity> where TEntity : Entity, new()
@@ -152,6 +181,8 @@ namespace InABox.Clients
         public Dictionary<string, string> Filters { get; set; }
         public Dictionary<string, string> Columns { get; set; }
         public Dictionary<string, string> Sorts { get; set; }
+
+        public override RequestMethod GetMethod() => RequestMethod.MultiQuery;
     }
 
     public class MultiQueryResponse : Response
@@ -176,6 +207,8 @@ namespace InABox.Clients
 
         public bool UsePIN { get; set; }
 
+        public override RequestMethod GetMethod() => RequestMethod.Validate;
+
     }
     public class ValidateResponse : Response
     {
@@ -198,6 +231,8 @@ namespace InABox.Clients
     public class Check2FARequest : Request
     {
         public string Code { get; set; }
+
+        public override RequestMethod GetMethod() => RequestMethod.Check2FA;
     }
 
     public class Check2FAResponse : Response
@@ -205,11 +240,17 @@ namespace InABox.Clients
         public bool Valid { get; set; }
     }
 
-    public class PingRequest : Request { }
+    public class PingRequest : Request
+    {
+        public override RequestMethod GetMethod() => RequestMethod.Ping;
+    }
 
     public class PingResponse : Response { }
     
-    public class InfoRequest : Request { }
+    public class InfoRequest : Request
+    {
+        public override RequestMethod GetMethod() => RequestMethod.Info;
+    }
 
     public class DatabaseInfo
     {
@@ -238,4 +279,17 @@ namespace InABox.Clients
         }
 
     }
+
+    public class RequestException : Exception
+    {
+        public StatusCode Status { get; set; }
+
+        public RequestMethod Method { get; set; }
+
+        public RequestException(string message, StatusCode status, Request request): base(message)
+        {
+            Status = status;
+            Method = request.GetMethod();
+        }
+    }
 }

+ 1 - 0
InABox.Server/Rest/RestListener.cs

@@ -18,6 +18,7 @@ using InABox.Server.WebSocket;
 using InABox.WebSocket.Shared;
 using NPOI.SS.Formula.Functions;
 using NPOI.XSSF.Streaming.Values;
+using RequestMethod = GenHTTP.Api.Protocol.RequestMethod;
 using StreamContent = GenHTTP.Modules.IO.Streaming.StreamContent;
 
 namespace InABox.API

+ 2 - 2
InABox.Server/RestService.cs

@@ -286,7 +286,7 @@ namespace InABox.API
             return response;
         }
 
-        public static LoadResponse<TEntity> Load(LoadRequest<TEntity> request)
+        /*public static LoadResponse<TEntity> Load(LoadRequest<TEntity> request)
         {
             var start = DateTime.Now;
 
@@ -322,7 +322,7 @@ namespace InABox.API
 
             GarbageCollection();
             return response;
-        }
+        }*/
 
         public static SaveResponse<TEntity> Save(SaveRequest<TEntity> request)
         {

+ 1 - 1
inabox.websocket.shared/NotifyResponse.cs

@@ -9,7 +9,7 @@ namespace InABox.WebSocket.Shared
 {
     public class NotifyRequest : Request
     {
-
+        public override RequestMethod GetMethod() => RequestMethod.Notify;
     }
 
     public class NotifyResponse : Response