我最近使用Nuget安装了T4MVC。我之前有一个旧版本工作正常,但是我有一个需要异步控制器的新要求。创建异步控制器后,由于与t4有关,我的项目无法编译。所以我使用Nuget更新了。
我现在遇到的问题是我的控制器工作正常,直到我最近更新了t4mvc。刷新我的代码后编译,但是当我调用异步操作时,它会在很长一段时间后返回并返回大量不正确的数据。而且至关重要的是,如果我在控制器中设置断点,它就不再能够击中它们了?!如果我将DocumentController.generated.cs恢复到最后一个工作版本,一切正常。
下面是我工作的旧DocumentController.generated.cs和没有的新文件。
任何人都可以帮我弄清楚这里发生了什么吗?我已经变得依赖于T4MVC,因为它非常好,但我真的无法避免这些异步行为。
OLD
// <auto-generated />
// This file was generated by a T4 template.
// Don't change it directly as your change would get overwritten. Instead, make changes
// to the .tt file (i.e. the T4 template) and save it to regenerate this file.
// Make sure the compiler doesn't complain about missing Xml comments
#pragma warning disable 1591
#region T4MVC
using System;
using System.Diagnostics;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using T4MVC;
namespace WebUI.Client.Controllers {
public partial class DocumentController {
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public DocumentController() { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected DocumentController(Dummy d) { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToAction(ActionResult result) {
var callInfo = result.GetT4MVCResult();
return RedirectToRoute(callInfo.RouteValueDictionary);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public DocumentController Actions { get { return MVC.Document; } }
[GeneratedCode("T4MVC", "2.0")]
public readonly string Area = "";
[GeneratedCode("T4MVC", "2.0")]
public readonly string Name = "Document";
static readonly ActionNamesClass s_actions = new ActionNamesClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionNamesClass ActionNames { get { return s_actions; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNamesClass {
public readonly string Index = "Index";
}
static readonly ViewNames s_views = new ViewNames();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewNames Views { get { return s_views; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ViewNames {
public readonly string Index = "~/Views/Document/Index.aspx";
}
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class T4MVC_DocumentController: WebUI.Client.Controllers.DocumentController
{
public T4MVC_DocumentController() : base(Dummy.Instance) { }
public override System.Web.Mvc.ActionResult Index() {
var callInfo = new T4MVC_ActionResult(Area, Name, ActionNames.Index);
return callInfo;
}
}
}
#endregion T4MVC
#pragma warning restore 1591
NEW
// <auto-generated />
// This file was generated by a T4 template.
// Don't change it directly as your change would get overwritten. Instead, make changes
// to the .tt file (i.e. the T4 template) and save it to regenerate this file.
// Make sure the compiler doesn't complain about missing Xml comments
#pragma warning disable 1591
#region T4MVC
using System;
using System.Diagnostics;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Web.Mvc.Html;
using System.Web.Routing;
using T4MVC;
namespace WebUI.Client.Controllers {
public partial class DocumentController {
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public DocumentController() { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected DocumentController(Dummy d) { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected RedirectToRouteResult RedirectToAction(ActionResult result) {
var callInfo = result.GetT4MVCResult();
return RedirectToRoute(callInfo.RouteValueDictionary);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.JsonResult GetDocumentListCompleted() {
return new T4MVC_JsonResult(Area, Name, ActionNames.GetDocumentListCompleted);
}
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.ActionResult GetDocumentThumbnailCompleted() {
return new T4MVC_ActionResult(Area, Name, ActionNames.GetDocumentThumbnailCompleted);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public DocumentController Actions { get { return MVC.Document; } }
[GeneratedCode("T4MVC", "2.0")]
public readonly string Area = "";
[GeneratedCode("T4MVC", "2.0")]
public readonly string Name = "Document";
static readonly ActionNamesClass s_actions = new ActionNamesClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionNamesClass ActionNames { get { return s_actions; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionNamesClass {
public readonly string Index = "Index";
public readonly string GetDocumentListCompleted = "GetDocumentListCompleted";
public readonly string GetDocumentThumbnailCompleted = "GetDocumentThumbnailCompleted";
}
static readonly ViewNames s_views = new ViewNames();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewNames Views { get { return s_views; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ViewNames {
public readonly string Index = "~/Views/Document/Index.aspx";
}
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class T4MVC_DocumentController: WebUI.Client.Controllers.DocumentController {
public T4MVC_DocumentController() : base(Dummy.Instance) { }
public override System.Web.Mvc.ActionResult Index() {
var callInfo = new T4MVC_ActionResult(Area, Name, ActionNames.Index);
return callInfo;
}
public override System.Web.Mvc.JsonResult GetDocumentListCompleted(Web.Gateway.DocumentMetaDataCollection clientDocuments) {
var callInfo = new T4MVC_JsonResult(Area, Name, ActionNames.GetDocumentListCompleted);
callInfo.RouteValueDictionary.Add("clientDocuments", clientDocuments);
return callInfo;
}
public override System.Web.Mvc.ActionResult GetDocumentThumbnailCompleted(System.IO.Stream document, string type) {
var callInfo = new T4MVC_ActionResult(Area, Name, ActionNames.GetDocumentThumbnailCompleted);
callInfo.RouteValueDictionary.Add("document", document);
callInfo.RouteValueDictionary.Add("type", type);
return callInfo;
}
}
}
#endregion T4MVC
#pragma warning restore 1591
这里要求的是我的DocumentController类的存根;
namespace WebUI.Client.Controllers
{
[Activated]
[ConcurrentSessionDisabled]
public partial class DocumentController : AsyncController
{
public readonly HashSet<string> ImageTypes = new HashSet<string>(new[] { "jpeg", "jpg", "png", "tif", "tiff", "bmp" });
public readonly HashSet<string> IgnoredImageTypes = new HashSet<string>(new[] { "tif", "tiff" });
public virtual ActionResult Index()
{
return RedirectToAction("List");
}
public virtual ActionResult List()
{
return View();
}
public virtual ActionResult Thumbnails(int id)
{
ViewData["documentId"] = id;
return View();
}
public void GetDocumentListAsync()
{
AsyncManager.Timeout = 30000;
AsyncManager.OutstandingOperations.Increment();
Task.Factory.StartNew((state) => {
Tuple<int, int> clientDetails = (Tuple<int, int>)state;
DocumentMetaDataCollection clientDocuments = DocumentHelper.GetClientDocuments(clientDetails.Item1, clientDetails.Item2);
AsyncManager.Parameters["clientDocuments"] = clientDocuments;
AsyncManager.OutstandingOperations.Decrement();
}, new Tuple<int, int>(Profile.User().ClientId, Profile.User().CrmAccountId));
}
public virtual JsonResult GetDocumentListCompleted(DocumentMetaDataCollection clientDocuments)
{
return Json(from document in clientDocuments.Documents
select new
{
Id = document.Id,
Values = document.Values,
}, JsonRequestBehavior.AllowGet);
}
public void GetDocumentFilenamesAsync(int id)
{
AsyncManager.Timeout = 5000;
AsyncManager.OutstandingOperations.Increment();
Task.Factory.StartNew((state) =>
{
int documentId = (int)state;
List<string> urls = DocumentHelper.GetUrlsForDocument(documentId);
AsyncManager.Parameters["documentId"] = documentId;
AsyncManager.Parameters["urls"] = urls;
AsyncManager.OutstandingOperations.Decrement();
}, id);
}
public JsonResult GetDocumentFilenamesCompleted(int documentId, List<string> urls)
{
IDictionary<int, string> filenameToUrl = new Dictionary<int, string>();
Regex illegalCharacters = new Regex("[^A-Za-z0-9_[-]:]");
int idCounter = 0;
foreach(string url in urls)
{
filenameToUrl.Add(++idCounter, url);
}
session_HoldDocumentUrls(documentId, filenameToUrl);
return Json(from file in filenameToUrl select new {
Name = filenameFrom(file.Value),
Id = file.Key
});
}
private string filenameFrom(string url)
{
return url.Substring(url.LastIndexOf('/') + 1, url.Length - (url.LastIndexOf('/') + 1));
}
public void GetThumbnailAsync(int documentId, int imageId)
{
AsyncManager.Timeout = 5000;
AsyncManager.OutstandingOperations.Increment();
string url = session_GetDocumentUrls(documentId).First(f => f.Key == imageId).Value;
Task.Factory.StartNew((state) => {
string fileUrl = (string)state;
thumbnailLoader(fileUrl);
}, url);
}
private void thumbnailLoader(string fileUrl)
{
Stream document = DocumentHelper.GetDocument(fileUrl);
string type = fileUrl.Substring(fileUrl.LastIndexOf('.') + 1, fileUrl.Length - (fileUrl.LastIndexOf('.') + 1)).ToLower();
if (ImageTypes.Contains(type))
{
document = ImageHelper.ResizeImage(document, 210);
type = "png";
}
AsyncManager.Parameters["document"] = document;
AsyncManager.Parameters["type"] = type;
AsyncManager.OutstandingOperations.Decrement();
}
public virtual ActionResult GetThumbnailCompleted(Stream document, string type)
{
switch (type)
{
case "png":
return new FileStreamResult(document, "image/png");
case "pdf":
return File(Links.Content.Images.pdf_256_png, "image/png");
default:
return File(Links.Content.Images.document_256_png, "image/png");
}
}
public void FileAsync(int documentId, int imageId)
{
if (session_GetDocumentUrls(documentId) == null)
{
return;
}
string url = session_GetDocumentUrls(documentId).First(f => f.Key == imageId).Value;
AsyncManager.Timeout = 5000;
AsyncManager.OutstandingOperations.Increment();
Task.Factory.StartNew((state) =>
{
string fileUrl = (string)state;
Stream document = DocumentHelper.GetDocument(fileUrl);
string type = fileUrl.Substring(fileUrl.LastIndexOf('.') + 1, fileUrl.Length - (fileUrl.LastIndexOf('.') + 1)).ToLower();
if (ImageTypes.Contains(type) && !IgnoredImageTypes.Contains(type))
{
document = ImageHelper.ConvertToPng(document);
type = "png";
}
AsyncManager.Parameters["document"] = document;
AsyncManager.Parameters["type"] = type;
AsyncManager.OutstandingOperations.Decrement();
}, url);
}
public virtual ActionResult FileCompleted(Stream document, string type)
{
if (document == null || type == null)
{
return RedirectToAction("List");
}
return new FileStreamResult(document, MimeHelper.Lookup("." + type));
}
}
}
更新7/4/11
嗨大卫,道歉,花了这么长时间才回到你身边,我一直在研究其他一些工作。
我已设法追查问题,希望您可以了解它并可能创建修复。
如果你看一下上面的第二个代码转储,这就是有问题的那个。问题是你已经创建了;
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public System.Web.Mvc.JsonResult GetDocumentListCompleted() {
return new T4MVC_JsonResult(Area, Name, ActionNames.GetDocumentListCompleted);
}
我不认为MVC会抛出错误,但确实如此;
2011-04-07 15:59:38,921 [41]致命的MvcApplication [(null)] - 发生未捕获的异常 System.Reflection.AmbiguousMatchException:由于以下方法之间存在歧义,在控制器类型“DocumentController”上查找方法“GetDocumentListCompleted”失败: WebUI.Client.Controllers.DocumentController类型上的System.Web.Mvc.JsonResult GetDocumentListCompleted(Web.Gateway.DocumentMetaDataCollection) System.Web.Mvc.JsonResult类型WebUI.Client.Controllers.DocumentController上的GetDocumentListCompleted() 在System.Web.Mvc.Async.AsyncActionMethodSelector.GetMethodByName(String methodName)
据我了解,MVC系统与我的代码和您创建的代码存在模糊匹配。
如果我注释掉上面的代码,那么一切都会正常运行。
您现在了解性质或问题吗?可以修复吗?
干杯,
瑞恩。
答案 0 :(得分:3)
更新(2011年4月12日):好的,我刚刚发布了一个新的T4MVC(2.6.51)版本,它忽略了异步完成方法。这应该为你解决问题!
T4MVC不支持异步操作。也就是说,您当然可以在控制器中执行异步操作,但不能使用T4MVC来引用它们
请参阅上一个有关该主题的问题: AsyncController in MVC2 and T4MVC: can they work together?