【问题标题】:Sitecore MVC OutputStream is not available when a custom TextWriter is used使用自定义 TextWriter 时,Sitecore MVC OutputStream 不可用
【发布时间】:2016-01-12 10:09:44
【问题描述】:

基于这个答案:https://stackoverflow.com/a/2343089/3889469

我在提交表单时无法提供 vCard。

@using (Html.BeginRouteForm(MvcSettings.SitecoreRouteName, FormMethod.Post, new { name = "vCard_verify", @class = "vCardVerify" }))
            {
                @Html.AntiForgeryToken()
                @Html.Sitecore().FormHandler("Content", "vCard")
                @Html.Hidden("vCardGuid")

                <div id="g-recaptcha-vCard"></div>
            }

控制器动作:

[HttpPost]
        [ValidateAntiForgeryToken]
        public vCardResult vCard()
        {
            NameValueCollection formNvc = Request.Form;
            string Guid =  formNvc["vCardGuid"];
            var context = new SitecoreContext();
            var person = context.GetItem<Person>(Guid);

            var card = new VCard
            {
                FirstName = person.First_Name,
                LastName = person.Last_Name,
                StreetAddress = "street",
                City = "city",
                State = "state",
                Zip = "zip",
                CountryName = "USA",
                Organization = "Org",
                JobTitle = person.Title,
                Phone = person.Phone,
                Fax = "Fax",
                Image = "image",
                HomePage = "google.com",
                Email = person.Email_Address
            };

            return new vCardResult(card);
        }

public class vCardResult : ActionResult
    {
        private VCard _card;

        protected vCardResult() { }

        public vCardResult(VCard card)
        {
            _card = card;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            var response = HttpContext.Current.Response; // context.HttpContext.Response;
            response.ContentType = "text/vcard";
            response.AddHeader("Content-Disposition", "attachment; fileName=" + _card.FirstName + " " + _card.LastName + ".vcf");

            var cardString = _card.ToString();
            var inputEncoding = Encoding.Default;
            var outputEncoding = Encoding.GetEncoding("windows-1257");
            var cardBytes = inputEncoding.GetBytes(cardString);
            var outputBytes = Encoding.Convert(inputEncoding,
                                    outputEncoding, cardBytes);

            response.BinaryWrite(outputBytes);
            //response.OutputStream.Write(outputBytes, 0, outputBytes.Length);
            //response.End();
        }
    }

    public class VCard
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Organization { get; set; }
        public string JobTitle { get; set; }
        public string StreetAddress { get; set; }
        public string Zip { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string CountryName { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
        public string Email { get; set; }
        public string HomePage { get; set; }
        public string Image { get; set; }

        public override string ToString()
        {
            var builder = new StringBuilder();
            builder.AppendLine("BEGIN:VCARD");
            builder.AppendLine("VERSION:4.0");
            // Name
            builder.AppendLine("N:" + LastName + ";" + FirstName + ";;;");
            // Full name
            builder.AppendLine("FN:" + FirstName + " " + LastName);
            //Company
            builder.AppendLine("ORG:" + Organization);
            //Title
            builder.AppendLine("TITLE:" + JobTitle);
            //Phone
            builder.AppendLine("TEL;TYPE=work:" + Phone);
            //Fax
            builder.AppendLine("TEL;TYPE=fax:" + Fax);
            // Address
            builder.Append("ADR;TYPE=work;LABEL=\"" + StreetAddress + "\n" + City + ", " + State + " " + Zip + "\n" + CountryName + "\":;;");
            builder.Append(StreetAddress + ";");
            builder.Append(City + ";");
            builder.Append(State + ";");
            builder.Append(Zip + ";");
            builder.AppendLine(CountryName);
            // Photo
            builder.AppendLine("PHOTO; MEDIATYPE = image / png:" + Image);
            //Site
            builder.AppendLine("URL;" + HomePage);
            //Email
            builder.AppendLine("EMAIL:" + Email);
            builder.AppendLine("END:VCARD");
            return builder.ToString();
        }
    }

我得到的错误是:使用自定义 TextWriter 时,OutputStream 不可用。 我相信在我的操作被调用之前已经发送了标头,但是我不确定替代方案是什么?如何强制下载文件并仍然使用 Sitecore 8 MVC 加载当前页面?

【问题讨论】:

    标签: asp.net-mvc sitecore asp.net-mvc-routing sitecore8 sitecore-mvc


    【解决方案1】:

    事实证明,我必须重新路由到一个新操作,以便能够在 sitecore 开始构建实际页面之前先传递我自己的标题。

    所以我的帖子功能改为:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult vCard(string vCardGuid)
    {
          if (string.IsNullOrEmpty(vCardGuid))
              return Redirect("/People");
    
          return RedirectToAction("DownloadvCard", new { vGuid = vCardGuid });
    }
    

    而新的DownloadvCard功能基本上就是旧的vCard功能

    [HttpGet]
    public vCardResult DownloadvCard(string vGuid)
    {
        var context = new SitecoreContext();
        var person = context.GetItem<Person>(vGuid);
        Item personItem = Database.GetDatabase("master").GetItem(ID.Parse(vGuid));
        //Photo
        ImageField img = personItem.Fields["Person Thumbnail"];
        MediaItem image = new MediaItem(img.MediaItem);
        var imageURL = MediaManager.GetMediaUrl(image, new MediaUrlOptions() { AbsolutePath = true, AlwaysIncludeServerUrl = true });
    
        //Url
        var options = LinkManager.GetDefaultUrlOptions();
        options.AlwaysIncludeServerUrl = true;
        string url = LinkManager.GetItemUrl(personItem, options);
    
        Location office = new Location();
        foreach (var loc in person.Offices)
        {
            office = loc;
            break;
        }
    
        var card = new VCard();
        card.FirstName = person.First_Name;
        card.LastName = person.Last_Name;
        card.StreetAddress = office.Location_Address;
        card.StreetAddress2 = office.Location_Address_2;
        card.City = office.Location_City;
        card.State = office.Location_State;
        card.Zip = office.Location_Zip;
        card.CountryName = "USA";
        card.Organization = "O'Connor Davies";
        card.JobTitle = person.Person_Title;
        card.Phone = person.Phone;
        card.Fax = office.Location_Fax;
        card.Image = imageURL.Replace(".ashx",".png");
        card.HomePage = url;
        card.Email = person.Email_Address;
    
    
        return new vCardResult(card);
    }
    

    其余部分保持不变。 快乐编码 ;)

    【讨论】:

    • 这很好用,但它不适用于 Sitecore 访问受限的 CD 实例:“您无权查看此目录或页面。”由于执行重定向的方法ping的默认路由是/sitecore/shell/api/sitecore/ControllerName/DownloadvCard
    • 我面临着类似的问题。正如上面评论中提到的@Marcel,CD 实例正在阻塞。有解决这个问题的最终解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多