T4MVC AsyncController

时间:2011-03-24 12:35:14

标签: .net nuget t4mvc asynccontroller

我最近使用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系统与我的代码和您创建的代码存在模糊匹配。

如果我注释掉上面的代码,那么一切都会正常运行。

您现在了解性质或问题吗?可以修复吗?

干杯,

瑞恩。

1 个答案:

答案 0 :(得分:3)

更新(2011年4月12日):好的,我刚刚发布了一个新的T4MVC(2.6.51)版本,它忽略了异步完成方法。这应该为你解决问题!


T4MVC不支持异步操作。也就是说,您当然可以在控制器中执行异步操作,但不能使用T4MVC来引用它们

请参阅上一个有关该主题的问题: AsyncController in MVC2 and T4MVC: can they work together?