Я нашел решение:
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using System;
using System.Reflection;
[assembly: Common.EnableFailureSimulation]
namespace Common
{
public class SimulateFailureMethodInfoWrapper : IMethodInfo
{
private readonly IMethodInfo m_mi;
public SimulateFailureMethodInfoWrapper(IMethodInfo mi)
{
m_mi = mi;
}
public ITypeInfo TypeInfo => m_mi.TypeInfo;
public MethodInfo MethodInfo => m_mi.MethodInfo;
public string Name => m_mi.Name;
public bool IsAbstract => m_mi.IsAbstract;
public bool IsPublic => m_mi.IsPublic;
public bool ContainsGenericParameters => m_mi.ContainsGenericParameters;
public bool IsGenericMethod => m_mi.IsGenericMethod;
public bool IsGenericMethodDefinition => m_mi.IsGenericMethodDefinition;
public ITypeInfo ReturnType => m_mi.ReturnType;
public T[] GetCustomAttributes<T>(bool inherit) where T : class => m_mi.GetCustomAttributes<T>(inherit);
public Type[] GetGenericArguments() => m_mi.GetGenericArguments();
public IParameterInfo[] GetParameters() => m_mi.GetParameters();
public object Invoke(object fixture, params object[] args)
{
var res = m_mi.Invoke(fixture, args);
Assert.Fail("Failure simulation");
return res;
}
public bool IsDefined<T>(bool inherit) where T : class => m_mi.IsDefined<T>(inherit);
public IMethodInfo MakeGenericMethod(params Type[] typeArguments) => m_mi.MakeGenericMethod(typeArguments);
}
[AttributeUsage(AttributeTargets.Assembly)]
public class EnableFailureSimulationAttribute : Attribute, ITestAction
{
private static string s_failTestMethod = GetParameterByName("!");
public ActionTargets Targets => ActionTargets.Test;
public void AfterTest(ITest test)
{
}
public void BeforeTest(ITest test)
{
if (test.MethodName == s_failTestMethod && test is Test testImpl)
{
testImpl.Method = new SimulateFailureMethodInfoWrapper(testImpl.Method);
s_failTestMethod = "!";
}
}
}
}
Альтернативным подходом было бы использование Moq
и макет интерфейса IMethodInfo
вместо реального класса SimulateFailureMethodInfoWrapper
.
В любом случае, это, кажется, работает отлично.
Вернуть FileResult
или FileStreamResult
из вашего действия в зависимости от того, файл существует или вы создаете его на лету.
public ActionResult GetPdf(string filename)
{
return File(filename, "application/pdf", Server.UrlEncode(filename));
}
Вы должны взглянуть на метод File контроллера. Это именно то, для чего это. Он возвращает FilePathResult вместо ActionResult.
Используйте тип файла .ashx и используйте тот же код
mgnoonan,
Вы можете сделать это, чтобы вернуть FileStream:
/// <summary>
/// Creates a new Excel spreadsheet based on a template using the NPOI library.
/// The template is changed in memory and a copy of it is sent to
/// the user computer through a file stream.
/// </summary>
/// <returns>Excel report</returns>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NPOICreate()
{
try
{
// Opening the Excel template...
FileStream fs =
new FileStream(Server.MapPath(@"\Content\NPOITemplate.xls"), FileMode.Open, FileAccess.Read);
// Getting the complete workbook...
HSSFWorkbook templateWorkbook = new HSSFWorkbook(fs, true);
// Getting the worksheet by its name...
HSSFSheet sheet = templateWorkbook.GetSheet("Sheet1");
// Getting the row... 0 is the first row.
HSSFRow dataRow = sheet.GetRow(4);
// Setting the value 77 at row 5 column 1
dataRow.GetCell(0).SetCellValue(77);
// Forcing formula recalculation...
sheet.ForceFormulaRecalculation = true;
MemoryStream ms = new MemoryStream();
// Writing the workbook content to the FileStream...
templateWorkbook.Write(ms);
TempData["Message"] = "Excel report created successfully!";
// Sending the server processed data back to the user computer...
return File(ms.ToArray(), "application/vnd.ms-excel", "NPOINewFile.xls");
}
catch(Exception ex)
{
TempData["Message"] = "Oops! Something went wrong.";
return RedirectToAction("NPOI");
}
}
Для загрузки файла PDF, вместо того, чтобы обрабатываться плагином PDF браузера:
public ActionResult DownloadPDF()
{
return File("~/Content/MyFile.pdf", "application/pdf", "MyRenamedFile.pdf");
}
, если вы хотите позволить браузеру Его поведение по умолчанию (плагин или загрузка), просто отправьте два параметра.
public ActionResult DownloadPDF()
{
return File("~/Content/MyFile.pdf", "application/pdf");
}
Вам нужно будет использовать третий параметр, чтобы указать имя для файла в диалоговом окне браузера.
Обновление: Charlino правильно, при прохождении третьего параметра (имя файла загрузки) Content-Distration: вложение;
добавляется в заголовок отклика HTTP. Мое решение было отправлено приложение \ Force-Download
в виде типа MIME, но это генерирует проблему с именем файла загрузки, поэтому третий параметр необходим для отправки хорошего имени файла, поэтому устранение необходимости загрузка загрузки .