修改图片缓存,增加新日志,JSON返回驼峰

This commit is contained in:
chfei committed 2026-09-15 14:08:24 +08:00
1 parent 72f16034ac
commit b86134357c
12 files changed
+432 -152

No files matched your search

@@ -1,5 +1,6 @@
using KJD_Web.Model;
using KJD_Web.Services;
using MAX.Core.Logger;
using MySqlX.XDevAPI.Common;
using System;
using System.Collections.Generic;
@@ -13,8 +14,9 @@ namespace KJD_Web.Controllers
public class ImageCacheController : ApiController
{
private readonly ImageCacheService _imageCacheService;
private readonly ILoggerFacade _logger;
public ImageCacheController(ImageCacheService imageCacheService)
public ImageCacheController(ImageCacheService imageCacheService, ILoggerFacade logger)
{
if (imageCacheService == null)
{
@@ -22,6 +24,7 @@ namespace KJD_Web.Controllers
}
_imageCacheService = imageCacheService;
_logger = logger;
}
@@ -54,40 +57,43 @@ namespace KJD_Web.Controllers
[HttpPost]
public IHttpActionResult AddOrUpdate([FromBody] ImageCacheUpdateUrlRequest[] requests)
{
try
if (requests == null || requests.Length == 0)
{
if (requests == null)
{
throw new Exception("参数错误");
}
foreach (var item in requests)
return Ok(ApiResult.Fail("参数不能为空"));
}
var failedItems = new List<string>();
foreach (var item in requests)
{
try
{
if (!_imageCacheService.AddOrUpdate(item.Md5, item.Platform, item.PlatformUrl))
{
throw new Exception("操作失败");
failedItems.Add(item.Md5);
}
}
return Ok(ApiResult.Success(true));
}
catch (Exception ex)
{
return Ok(ApiResult.Fail(ex.Message));
catch (Exception ex)
{
_logger.Error(ex, $"AddOrUpdate 失败, Md5={item.Md5}");
failedItems.Add(item.Md5);
}
}
return failedItems.Count == 0
? Ok(ApiResult.Success(true))
: Ok(ApiResult.Fail($"部分图片失败", data: failedItems));
}
public class ImageCacheBatchQueryRequest
{
public List<string> Md5s { get; set; }
public byte? Platform { get; set; }
}
public class ImageCacheUpdateUrlRequest
{
public string Md5 { get; set; }
public byte Platform { get; set; }
public string PlatformUrl { get; set; }
}
}
public class ImageCacheBatchQueryRequest
{
public List<string> Md5s { get; set; }
public byte? Platform { get; set; }
}
public class ImageCacheUpdateUrlRequest
{
public string Md5 { get; set; }
public byte Platform { get; set; }
public string PlatformUrl { get; set; }
}
}
@@ -0,0 +1,69 @@
using System;
namespace MAX.Core.Logger
{
/// <summary>
/// 日志操作
/// </summary>
public interface ILoggerFacade
{
/// <summary>
/// 调试级别是否启用
/// </summary>
bool IsDebugEnabled { get; }
/// <summary>
/// 调试
/// </summary>
void Debug(Exception ex, string message);
/// <summary>
/// 调试
/// </summary>
/// <param name="message">日志消息</param>
void Debug(string message);
/// <summary>
/// 信息
/// </summary>
void Info(Exception ex, string message);
/// <summary>
/// 信息
/// </summary>
/// <param name="message">日志消息</param>
void Info(string message);
/// <summary>
/// 警告
/// </summary>
void Warn(Exception ex, string message);
/// <summary>
/// 警告
/// </summary>
/// <param name="message">日志消息</param>
void Warn(string message);
/// <summary>
/// 错误
/// </summary>
void Error(Exception ex, string message);
/// <summary>
/// 错误
/// </summary>
/// <param name="message">日志消息</param>
void Error(string message);
/// <summary>
/// 致命错误
/// </summary>
void Fatal(Exception ex, string message);
/// <summary>
/// 致命错误
/// </summary>
/// <param name="message">日志消息</param>
void Fatal(string message);
void Error(Exception ex);
/// <summary>
/// 写入日志
/// </summary>
/// <param name="message"></param>
/// <param name="level"></param>
void Log(string message, LogLevel level);
}
}
+16
View File
@@ -0,0 +1,16 @@
namespace MAX.Core.Logger
{
/// <summary>
/// 日志等级
/// </summary>
public enum LogLevel
{
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4,
Fatal = 5,
None = 6
}
}
+152
View File
@@ -0,0 +1,152 @@
using MAX.Core.Logger;
using MySqlX.XDevAPI;
using NLog;
using System;
using LLogLevel = MAX.Core.Logger.LogLevel;
using NLogLevel = NLog.LogLevel;
namespace MAX.Framework.Logger
{
public class NLogger : ILoggerFacade
{
private static NLogger mySelf;//= default(T);
public static NLogger Instance
{
get
{
if (mySelf == null)
{
mySelf = new NLogger();
}
return mySelf;
}
}
private readonly ILogger _log;
private NLogger()
{
_log = LogManager.GetCurrentClassLogger();
}
public bool IsDebugEnabled { get; private set; } = true;
public void Debug(Exception ex, string message)
{
Execute(NLogLevel.Debug, ex, message);
}
public void Debug(string message)
{
Execute(NLogLevel.Debug, message);
}
public void Error(Exception ex)
{
Execute(NLogLevel.Error, ex);
}
public void Error(Exception ex, string message)
{
Execute(NLogLevel.Error, ex, message);
}
public void Error(string message)
{
Execute(NLogLevel.Error, message);
}
public void Fatal(Exception ex, string message)
{
Execute(NLogLevel.Fatal, ex, message);
}
public void Fatal(string message)
{
Execute(NLogLevel.Fatal, message);
}
public void Info(Exception ex, string message)
{
Execute(NLogLevel.Info, ex, message);
}
public void Info(string message)
{
Execute(NLogLevel.Info, message);
}
public void Warn(Exception ex, string message)
{
Execute(NLogLevel.Warn, ex, message);
}
public void Warn(string message)
{
Execute(NLogLevel.Warn, message);
}
public void Log(string message, LLogLevel level)
{
NLogLevel lv = NLogLevel.Info;
switch (level)
{
case LLogLevel.Trace:
lv = NLogLevel.Trace;
break;
case LLogLevel.Debug:
lv = NLogLevel.Debug;
break;
case LLogLevel.Info:
lv = NLogLevel.Info;
break;
case LLogLevel.Warn:
lv = NLogLevel.Warn;
break;
case LLogLevel.Error:
lv = NLogLevel.Error;
break;
case LLogLevel.Fatal:
lv = NLogLevel.Fatal;
break;
case LLogLevel.None:
lv = NLogLevel.Off;
break;
}
Execute(lv, message);
}
/// <summary>
/// 是否启用
/// </summary>
private bool Enabled(NLogLevel level)
{
if (level > NLogLevel.Debug)
{
return true;
}
return IsDebugEnabled;
}
/// <summary>
/// 执行
/// </summary>
private void Execute(NLogLevel level, Exception ex, string message = "")
{
if (Enabled(level))
{
_log.Log(level, ex, message, null);
}
}
/// <summary>
/// 执行
/// </summary>
private void Execute(NLogLevel level, string message)
{
if (Enabled(level))
{
_log.Log(level, message);
}
}
}
}
+40 -38
View File
@@ -2,12 +2,14 @@
using Autofac.Integration.WebApi;
using FreeSql;
using KJD_Web.Utils;
using MySql.Data.MySqlClient;
using MAX.Core.DependencyInjection;
using MAX.Core.Logger;
using MAX.Framework.Logger;
using MySql.Data.MySqlClient;
using NLog;
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Web;
@@ -21,7 +23,7 @@ namespace KJD_Web
{
protected void Application_Start(object sender, EventArgs e)
{
LogHelper.Info("应用程序启动");
NLogger.Instance.Info("应用程序启动");
var container = BuildContainer();
// 让 Web API 用 Autofac 解析 Controller
@@ -42,7 +44,7 @@ namespace KJD_Web
// 注册 Web API 所有 Controller
builder.RegisterApiControllers(appAssembly);
builder.RegisterInstance(NLogger.Instance).As<ILoggerFacade>().SingleInstance();
#region 注册所有IOC接口
Type typeSingleton = typeof(ISingletonDependency);
@@ -113,50 +115,50 @@ namespace KJD_Web
string hPath = Request.Url.LocalPath.ToString();
//if (!hPath.Contains(".asmx") && hPath.Contains("/user/"))
//{
//hPath = hPath.Replace("/user/", "/UserService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/user/", "/UserService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/shop/"))
//{
//hPath = hPath.Replace("/shop/", "/ShopService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/shop/", "/ShopService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/update/"))
//{
//hPath = hPath.Replace("/update/", "/UpdateService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/update/", "/UpdateService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/order/"))
//{
//hPath = hPath.Replace("/order/", "/OrderService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/order/", "/OrderService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/product/"))
//{
//hPath = hPath.Replace("/product/", "/ProductService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/product/", "/ProductService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/product_third/"))
//{
//hPath = hPath.Replace("/product_third/", "/ProductThirdService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/product_third/", "/ProductThirdService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/price/"))
//{
//hPath = hPath.Replace("/price/", "/PriceService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/price/", "/PriceService.asmx/");
//Context.RewritePath(hPath);
//}
//if (!hPath.Contains(".asmx") && hPath.Contains("/bxx_user/"))
//{
//hPath = hPath.Replace("/bxx_user/", "/BXXUserService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/bxx_user/", "/BXXUserService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/bxx_shop/"))
//{
//hPath = hPath.Replace("/bxx_shop/", "/BXXShopService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/bxx_shop/", "/BXXShopService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/update/"))
//{
@@ -165,30 +167,30 @@ namespace KJD_Web
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/bxx_product/"))
//{
//hPath = hPath.Replace("/bxx_product/", "/BXXProductService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/bxx_product/", "/BXXProductService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/bxx_product_third/"))
//{
//hPath = hPath.Replace("/bxx_product_third/", "/BXXProductThirdService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/bxx_product_third/", "/BXXProductThirdService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/bxx_price/"))
//{
//hPath = hPath.Replace("/bxx_price/", "/BXXPriceService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/bxx_price/", "/BXXPriceService.asmx/");
//Context.RewritePath(hPath);
//}
//if (!hPath.Contains(".asmx") && hPath.Contains("/dyxd_user/"))
//{
//hPath = hPath.Replace("/dyxd_user/", "/DYUserService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/dyxd_user/", "/DYUserService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/dyxd_shop/"))
//{
//hPath = hPath.Replace("/dyxd_shop/", "/DYShopService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/dyxd_shop/", "/DYShopService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/update/"))
//{
@@ -216,19 +218,19 @@ namespace KJD_Web
//}
//if (!hPath.Contains(".asmx") && hPath.Contains("/wxxd_product/"))
//{
//hPath = hPath.Replace("/wxxd_product/", "/WXProductService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/wxxd_product/", "/WXProductService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/wxxd_order/"))
//{
//hPath = hPath.Replace("/wxxd_order/", "/WXOrderService.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/wxxd_order/", "/WXOrderService.asmx/");
//Context.RewritePath(hPath);
//}
//else if (!hPath.Contains(".asmx") && hPath.Contains("/wxxd_shop_revenue_statistics/"))
//{
//hPath = hPath.Replace("/wxxd_shop_revenue_statistics/", "/WXShopRevenueStatistics.asmx/");
//Context.RewritePath(hPath);
//hPath = hPath.Replace("/wxxd_shop_revenue_statistics/", "/WXShopRevenueStatistics.asmx/");
//Context.RewritePath(hPath);
//}
// 请求录制:捕获请求链接与请求内容,用于迁移后的回放校验
//try { ApiRequestLogger.BeginRequest(Context); } catch { }
+13 -8
View File
@@ -26,16 +26,18 @@
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>12</LangVersion>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<LangVersion>12</LangVersion>
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
@@ -203,6 +205,9 @@
<Compile Include="Controllers\UpdateController.cs" />
<Compile Include="Controllers\ShopController.cs" />
<Compile Include="Controllers\UserController.cs" />
<Compile Include="Core\Logger\ILoggerFacade.cs" />
<Compile Include="Core\Logger\LogLevel.cs" />
<Compile Include="Core\Logger\NLogger.cs" />
<Compile Include="DependencyInjection\IScopedDependency.cs" />
<Compile Include="DependencyInjection\ISingletonDependency.cs" />
<Compile Include="DependencyInjection\ITransientDependency.cs" />
+69 -69
View File
@@ -1,80 +1,80 @@
using System;
using NLog;
//using System;
//using NLog;
namespace KJD_Web
{
public static class LogHelper
{
private static Logger _logger;
//namespace KJD_Web
//{
// public static class LogHelper
// {
// private static Logger _logger;
// 静态构造函数,获取Logger实例
static LogHelper()
{
_logger = LogManager.GetCurrentClassLogger();
}
// // 静态构造函数,获取Logger实例
// static LogHelper()
// {
// _logger = LogManager.GetCurrentClassLogger();
// }
// 获取日志记录器
public static Logger Logger
{
get { return _logger; }
}
// // 获取日志记录器
// public static Logger Logger
// {
// get { return _logger; }
// }
// 便捷方法:记录信息
public static void Info(string message, params object[] args)
{
_logger.Info(message, args);
}
// // 便捷方法:记录信息
// public static void Info(string message, params object[] args)
// {
// _logger.Info(message, args);
// }
// 便捷方法:记录错误
public static void Error(string message, params object[] args)
{
_logger.Error(message, args);
}
// // 便捷方法:记录错误
// public static void Error(string message, params object[] args)
// {
// _logger.Error(message, args);
// }
// 便捷方法:记录错误(含异常)
public static void Error(Exception ex, string message = null, params object[] args)
{
if (string.IsNullOrEmpty(message))
_logger.Error(ex);
else
_logger.Error(ex, message, args);
}
// // 便捷方法:记录错误(含异常)
// public static void Error(Exception ex, string message = null, params object[] args)
// {
// if (string.IsNullOrEmpty(message))
// _logger.Error(ex);
// else
// _logger.Error(ex, message, args);
// }
// 便捷方法:记录警告
public static void Warn(string message, params object[] args)
{
_logger.Warn(message, args);
}
// // 便捷方法:记录警告
// public static void Warn(string message, params object[] args)
// {
// _logger.Warn(message, args);
// }
// 便捷方法:记录调试
public static void Debug(string message, params object[] args)
{
_logger.Debug(message, args);
}
// // 便捷方法:记录调试
// public static void Debug(string message, params object[] args)
// {
// _logger.Debug(message, args);
// }
// 便捷方法:记录跟踪
public static void Trace(string message, params object[] args)
{
_logger.Trace(message, args);
}
// // 便捷方法:记录跟踪
// public static void Trace(string message, params object[] args)
// {
// _logger.Trace(message, args);
// }
// 记录方法进入(用于方法调用跟踪)
public static void LogMethodEntry(string methodName, params object[] parameters)
{
if (_logger.IsTraceEnabled)
{
_logger.Trace("进入方法: {0} (参数: {1})", methodName,
string.Join(", ", parameters));
}
}
// // 记录方法进入(用于方法调用跟踪)
// public static void LogMethodEntry(string methodName, params object[] parameters)
// {
// if (_logger.IsTraceEnabled)
// {
// _logger.Trace("进入方法: {0} (参数: {1})", methodName,
// string.Join(", ", parameters));
// }
// }
// 记录方法退出
public static void LogMethodExit(string methodName, object result = null)
{
if (_logger.IsTraceEnabled)
{
_logger.Trace("退出方法: {0} (返回值: {1})", methodName, result ?? "void");
}
}
}
}
// // 记录方法退出
// public static void LogMethodExit(string methodName, object result = null)
// {
// if (_logger.IsTraceEnabled)
// {
// _logger.Trace("退出方法: {0} (返回值: {1})", methodName, result ?? "void");
// }
// }
// }
//}
+10 -4
View File
@@ -1,5 +1,6 @@
using KJD_Web.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -20,7 +21,7 @@ namespace KJD_Web
if (actionExecutedContext.Response != null &&
actionExecutedContext.Response.StatusCode == HttpStatusCode.NotFound)
{
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(
HttpStatusCode.NotFound, ApiResult.Fail("请求失败", ResultCode.NotFound));
@@ -38,9 +39,14 @@ namespace KJD_Web
if (response.StatusCode != HttpStatusCode.OK)
{
response.Content = new StringContent(
JsonConvert.SerializeObject(ApiResult.Fail("请求失败", ResultCode.NotFound)),
Encoding.UTF8,
"application/json");
JsonConvert.SerializeObject(
ApiResult.Fail("请求失败", ResultCode.NotFound),
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
}),
Encoding.UTF8,
"application/json");
}
return response;
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<DeleteExistingFiles>false</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\app.publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
</PropertyGroup>
</Project>
+5 -2
View File
@@ -1,6 +1,7 @@
using FreeSql;
using FreeSql.DataAnnotations;
using MAX.Core.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -10,21 +11,23 @@ namespace KJD_Web.Services
[Table(Name = "images_0")]
public class ImageCacheEntity
{
[JsonIgnore]
[Column(Name = "id", IsIdentity = true, IsPrimary = true)]
public long id { get; set; }
[Column(Name = "platform")]
public byte platform { get; set; }
[JsonProperty("md5")]
[Column(Name = "source_url_md5", StringLength = 32)]
public string source_url_md5 { get; set; }
[Column(Name = "platform_url", StringLength = 1000)]
public string platform_url { get; set; }
[JsonIgnore]
[Column(Name = "create_time")]
public DateTime create_time { get; set; }
[JsonIgnore]
[Column(Name = "update_time")]
public DateTime update_time { get; set; }
}
+1 -1
View File
@@ -6,7 +6,7 @@
<configuration>
<connectionStrings>
<add name="ConnKJD" connectionString="Max Pool Size=512;Database='kjd';Data Source='nj-cynosdbmysql-grp-hl51pkfr.sql.tencentcdb.com';Port=27660;User Id='kjd';Password='Temukjd0625';Charset=utf8mb4;" />
<!--<add name="ConnKJD" connectionString="Server=localhost;Port=3306;Database=mysql;Uid=root;Pwd=123456;"/>-->
<!--<add name="ConnKJD" connectionString="Server=192.168.0.200;Port=3306;Database=mysql;Uid=root;Pwd=123456;"/>-->
<add name="ConnKJDBAK" connectionString="Max Pool Size=512;Database='kjd';Data Source='nj-cynosdbmysql-grp-9s7x16mt.sql.tencentcdb.com';Port=24049;User Id='kjdbak';Password='Temukjd0126';Charset=utf8mb4;" />
<add name="UpdateVersion" connectionString="99999" />
<add name="UpdateFileDir" connectionString="C:\inetpub\wwwroot\kjd_update" />
+8 -2
View File
@@ -1,4 +1,5 @@
using System;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
@@ -23,10 +24,15 @@ namespace KJD_Web
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var jsonFormatter = config.Formatters.JsonFormatter;
jsonFormatter.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Filters.Add(new NotFoundMessageFilter());
config.MessageHandlers.Add(new NotFoundMessageHandler());
}
}
}