人们如何在.NET Core 2应用程序中单元测试他们的Startup.cs类?所有功能似乎都是由静态扩展方法提供的,这些方法不可模拟?
如果您采用此ConfigureServices
方法为例:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BlogContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
}
Run Code Online (Sandbox Code Playgroud)
如何编写测试以确保调用AddDbContext(...)和AddMvc(),通过Extensions方法实现所有这些功能的选择似乎使其不可测试?
我将在docs.microsoft上发布以下帖子,从ASP.NET Core 1.x迁移到v2.0:https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to -2x /
我差不多完成了那篇文章中提到的所有变化.但是有一个错误导致了麻烦.
这是我的Program.cs文件:
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
namespace MeridiaCoreAPI
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((hostContext, config) =>
{
// delete all default configuration providers
config.Sources.Clear();
config.AddJsonFile("myconfig.json", optional: true);
})
.Build();
}
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
Suppression State
Error CS0103 The name 'WebHost' does not exist in the current context
Run Code Online (Sandbox Code Playgroud)
任何解决方案,解决方法或提示都将受到高度赞赏.谢谢.
为什么ASP.NET的所有响应都包含Cache-Control: private
?即使是404响应?IIS中是否有设置此默认值的东西,有没有办法配置它?或者ASP.NET中有什么设置这个?
对于动态内容(即所有MVC结果),我不希望它被浏览器缓存,因为它是动态的,可以随时更改.静态内容托管在CDN上,因此IIS不提供服务.
为了澄清,我非常理解什么Cache-Control: private
是,之间的区别private
,public
,no-store
,等以及如何/何时使用它们.我的问题是Cache-Control: private
IIS/ASP.NET默认添加的原因以及如何防止默认情况下添加它.据我所知,它可以被缓存动态页面是有用的,但在我的应用程序,我不希望缓存动态页面/响应.例如,我不想XHR JSON响应被缓存,因为它们含有动态内容.不幸的是,服务器会Cache-Control: private
自动添加所有响应,因此我必须在任何地方手动覆盖它.
如何重现:使用MVC项目打开visual studio并创建一个新的ASP.NET框架(是的,框架,不是Core.我们无法将系统迁移到核心).现在在IIS Express中启动项目(只需按下播放按钮),然后在浏览器中使用F12 devtools查看http响应.你会看到它包含Cache-Control: private
.我的问题是,添加此标题的是什么,以及如何防止默认情况下添加它?
在ASP.NET Core 2.0应用程序中,我尝试OnActionExecuting
在执行Controller的变体之前执行全局过滤器.预期的行为是我可以在全局之前准备一些东西并将结果值传递给控制器.然而,当前的行为是执行的顺序被设计颠倒了.
文档告诉我默认的执行顺序:
从Controller基类继承的每个控制器都包含OnActionExecuting和OnActionExecuted方法.这些方法包装为给定操作运行的过滤器:在任何过滤器之前调用OnActionExecuting,并在所有过滤器之后调用OnActionExecuted.
这导致我解释Controller OnActionExecuting
在任何过滤器之前执行.说得通.但是文档还声明可以通过实现来覆盖默认顺序IOrderedFilter
.
我尝试在过滤器中实现这一点是这样的:
public class FooActionFilter : IActionFilter, IOrderedFilter
{
// Setting the order to 0, using IOrderedFilter, to attempt executing
// this filter *before* the BaseController's OnActionExecuting.
public int Order => 0;
public void OnActionExecuting(ActionExecutingContext context)
{
// removed logic for brevity
var foo = "bar";
// Pass the extracted value back to the controller
context.RouteData.Values.Add("foo", foo);
}
}
Run Code Online (Sandbox Code Playgroud)
此过滤器在启动时注册为:
services.AddMvc(options …
Run Code Online (Sandbox Code Playgroud) 我TcpListener
上课,我正在async/await
阅读和写作.
对于这个服务器,我创建了单个数据库实例,我准备了所有数据库查询.
但是对于一个以上,TcpClient
我一直在例外:
MySql.Data.MySqlClient.MySqlException
发生了类型的异常,MySql.Data.dll
但未在用户代码中处理附加信息:已经有一个
DataReader
与此相关的开放Connection
,必须先关闭.
如果我理解正确的话,那么一次数据库查询就不会超过一个async
客户端.
所以我只是在我的查询中添加了锁,这样一切似乎都很好.
// One MySqlConnection instance for whole program.
lock (thisLock)
{
var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT Count(*) FROM logins WHERE username = @user AND password = @pass";
cmd.Parameters.AddWithValue("@user", username);
cmd.Parameters.AddWithValue("@pass", password);
var count = int.Parse(cmd.ExecuteScalar().ToString());
return count > 0;
}
Run Code Online (Sandbox Code Playgroud)
我也尝试使用这个方法为每个查询创建新连接,如SO社区的某个人所提到的,但这个方法比锁慢得多:
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open(); // This takes +- 35ms and makes worse …
Run Code Online (Sandbox Code Playgroud) 我正在开发一个Fluent Api来提供相当可配置的服务,并且只是尝试为下面的问题提供一个简洁的解决方案.
我有一个这样的课
public class WindowVm : DialogResultBase<MyReturnType>
Run Code Online (Sandbox Code Playgroud)
一切都很好,但是任何人都可以想到一种方法来实现以下,而不必详细说明给定的第二种通用类型即
public IDialogWithResult<TViewModel, TSomeReturnType> DialogWithResult<TViewModel,TSomeReturnType>(object owner = null)
where TViewModel : DialogResultBase<TSomeReturnType>
Run Code Online (Sandbox Code Playgroud)
IDialogWithResult<TViewModel, TSomeReturnType>
即使我必须在2个陈述中做到这一点,我真的只对结果感兴趣
所以我可以打电话
.DialogWithResult<WindowVm>()
Run Code Online (Sandbox Code Playgroud)
我知道所有信息都在那里并在编译时声明,我也知道这是部分推理及其全部或全部.然而,我只是想知道是否有一些技巧,而不必重新声明
.DialogWithResult<WindowVm, ResultType>();
Run Code Online (Sandbox Code Playgroud)
此外,我有一个方法需要ResultType作为(你猜对了)一个结果类型
ResultType MyResult = ...DialogWithResult<WindowVm, ResultType>()
.ShowModal();
Run Code Online (Sandbox Code Playgroud)
我的意思
ResultType
是,在游戏的这一点上真的是多余的,因为它已经被宣布了WindowVm
.如果消费者不必去寻找它(即使它意味着超过一步),那将是很好的
我知道我可以使用设置我的服务的基本路径,app.UsePathBase("/AppPath");
以便我的 API 可用,http://example.com/AppPath/controller1
但如果我这样做,我的 API 也可以从根路径获取http://example.com/controller1
。如何禁用从根路径访问?
我也尝试使用这样的路线, app.UseMvc(routes => routes.MapRoute("default", "IRate/{controller}/{action}/{id?}"));
但它有同样的问题。
我想这样做的原因是因为当它在生产中部署时,它将部署在应用程序前缀下(而不是作为根应用程序),并且当我在调试期间在本地主机上运行 API 时,我想模拟生产条件。
所以我最近开始构建一个asp.net核心应用程序,并且我正在使用SeriLog进行日志记录.这工作正常,直到最近我发现大多数情况下异常的堆栈跟踪没有转移到我的日志.我正在使用.WriteTo.RollingFile()方法在Startup.cs中的LoggerConfiguration中写入.txt文件,如此
public void ConfigureServices(IServiceCollection services)
{
//add a bunch of services
services.AddLogging(builder =>
{
builder.AddConsole();
builder.AddDebug();
var logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.WithExceptionDetails()
.WriteTo.RollingFile(Configuration.GetValue<string>("LogFilePath") + "-{Date}.txt", LogEventLevel.Information,
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] ({SourceContext}) {Message}{NewLine}{Exception}")
.CreateLogger();
builder.AddSerilog(logger);
});
services.AddMvc();
}
Run Code Online (Sandbox Code Playgroud)
在我的loggerFactory中,我添加了这行代码的Serilog
loggerFactory.AddSerilog();
Run Code Online (Sandbox Code Playgroud)
我的BuildWebHost方法没有.UserSerilog(),如下所示:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
Run Code Online (Sandbox Code Playgroud)
这个方法作为Main
Program.cs 中我方法的最后一步被调用.阅读Serilog的文档,RollingFile的outputTemplate中的{Exception}也应该记录异常的堆栈跟踪.但是,例如我记录这样的错误(使用Microsoft.Extensions.Logging.ILogger
)
_log.LogError("Exception thrown when trying to convert customer viewmodel to model or getting data from the database with id: " + id, …
Run Code Online (Sandbox Code Playgroud) 我正在使用通用工厂类,其中通用部分是正在使用的派生类.正常用法很明确:BaseClass<DerivedA> C = new BaseClass<DerivedA>().
现在虽然我正在尝试将属性注入到我使用这些类的类中.为此,我尝试将Type作为参数(以便我可以注入正在使用的派生类).
现在虽然我有点不知所措,尽管寻找例子并自己尝试.而我现在想知道:这样的构造是否可以使用?如果是这样,我如何实例化该类并使用Exists和ExistsB?
用法:
public class MyMainClass
{
object _ClassInstance; // BaseClass<DerivedA> or BaseClass<DerivedB>
public MyyMainClass(Type typeIWant)
{
.....
}
}
....
MyMainClass a = new MyMainClass(typeof(DerivedA));
MyMainClass b = new MyMainClass(typeof(DerivedB));
Run Code Online (Sandbox Code Playgroud)
通用类:
public abstract class BaseClass<T> where T: BaseClass<T>, new()
{
...
public bool Exists(int a) {...}
}
Run Code Online (Sandbox Code Playgroud)
派生类:
public class DerivedA :BaseClass<DerivedA>
{
...
}
public class DerivedB :BaseClass<DerivedB>
{
...
public bool ExistsB(string a) {...}
}
Run Code Online (Sandbox Code Playgroud) c# ×8
asp.net-core ×6
.net-core ×2
generics ×2
ado.net ×1
asp.net ×1
asp.net-mvc ×1
async-await ×1
caching ×1
connection ×1
iis ×1
logging ×1
mocking ×1
mysql ×1
razor ×1
serilog ×1
stack-trace ×1
unit-testing ×1