【问题标题】:cXML PunchOutSetupRequest and PunchOutSetupResponse examples in C#C# 中的 cXML PunchOutSetupRequest 和 PunchOutSetupResponse 示例
【发布时间】:2014-08-26 21:39:55
【问题描述】:

我正在尝试在我们的 eComm 网站上实施打孔目录。老实说,cXML 的文档是一团糟,所有的代码示例都在 javascript 和/或 VB.Net 中(我使用 C#,不想尝试翻译)。有没有人有示例或示例说明如何接收 PunchOutSetupRequest XML,然后使用 C# 发送 PunchOutSetupResponse XML?我在互联网上找不到任何东西(我已经找了两天了)......

我希望我可以在 ActionResult 中执行此操作(相对于建议的“启动页面”)。

我完全是打孔的菜鸟,在这里真的可以使用一些帮助。老板们都很咄咄逼人,所以任何帮助都将不胜感激。关于如何使这项工作的建议也将不胜感激。

对于问题(请求)的含糊之处,我向所有人道歉。

【问题讨论】:

    标签: c# cxml


    【解决方案1】:

    这不是微不足道的,但这应该可以帮助您入门。

    您需要 3 个通用处理程序 (.ashx):Setup、Start 和 Order....

    Setup 和 Order 将接收内容类型为“text/xml”的 HTTP Post。如果需要将 XML 转换为字符串,请查看 HttpRequest.InputStream。从那里,查看 LINQ-to-XML 以挖掘出您想要的数据。您对这两者的 HTTP 响应也将是内容类型“text/xml”和 UTF8 编码,返回 CXML 作为记录...使用 LINQ-to-XML 来生成。

    Setup 处理程序将需要验证凭据并返回一个带有唯一 QueryString 令牌的 URL,该令牌指向 Start 处理程序。不要期望 Setup 和 Start 之间的会话持久性,因为它们不是来自同一个调用者。此处理程序需要为您从 cXML 中提取的令牌和相关数据创建一个应用程序对象。

    Start 处理程序将作为简单的 GET 调用,并且需要将 QueryString 中的令牌匹配到适当的应用程序对象,将该数据复制到会话,然后执行 response.redirect 到您站点中的任何页面您希望买家登陆。

    一旦他们在购物车中添加了一些东西并准备结账,您就会将他们带到具有嵌入式表单的页面(不要与回发到服务器的 ASP.Net 表单混淆)和一个提交按钮(同样,不是 ASP.Net 按钮)。从您的 Setup 处理程序中,您捕获了一个指向此表单的 Post 的 URL,并且在表单中您将拥有一个隐藏的输入标记,其中 UTF8 编码的 CXML Punchout Order 作为使用 LINQ-to-XML 生成的值注入。强烈建议对该值进行 Base64 编码,以避免 ASP.Net 在渲染期间弄乱它包含的标签,并根据文档将隐藏的输入命名为“cxml-base64”。结果是表单被客户端发布到您客户的服务器而不是您的服务器,他们的服务器将提取 CXML Punchout Order 并结束您的访问者会话。

    订单处理程序将收到一个 CXML OrderRequest,就像安装程序一样,您将把它转储到一个字符串中,然后使用 LINQ-to-XML 对其进行解析并对其采取行动。同样,您将获得用于验证的凭据,可能是要处理的信用卡,以及订单项目、收货人等。请注意,OrderRequest 可能不包含 Punchout Order 中的所有项目,因为您客户的系统在向您提交最终 OrderRequest 之前,side 可能会删除项目甚至更改项目数量。在 Punchout Order 发布给他们后,OrderRequest 可能会在几分钟、几天、几周内或永远不会返回给您……不要费心存储购物车数据以希望稍后将其与订单匹配。

    最后一点...买家可能会在嵌入其基于 Web 的采购 UI 中的 iframe 中体验您的网站,因此请进行相应的设计。

    如果您需要更多信息,请回复此内容,我会回复您。

    更新...其他注意事项: 与买方讨论他们希望如何处理故障,尤其是订单,因为您可以选择。 1) 详尽评估您收到的 CXML 中的所有内容,如果有任何错误,则返回 200 以外的响应代码,或者 2) 始终返回 200 Success 并处理带外的任何问题,或生成拒绝订单的 ConfirmationRequest。我的经验是两者混合效果最好。当然,如果凭据失败,您应该抛出非 200,但您可能不希望(或能够)运行信用卡或在线验证库存可用性。您的买方系统可能无法处理数十种可能的故障,和/或可能无法向用户显示您的故障信息,以便他们进行更正。我见过一些系统会彻底丢弃任何非 200 响应代码,只是盲目地每隔数小时或数天反复重试提交,直到它放弃完整性检查,而其他系统会以不同方式处理特定范围内的响应代码比其他的,例如 4xx 调用重试,而 5xx 被视为致命。请记住,设置和订单并非直接来自用户……他们的采购系统是在内部生成的。


    更新...回答有关如何测试事物的评论...

    您将使用与生成出站 ConfirmationRequest、ShipNoticeRequest 和 InvoiceDetailRequest 相同的方法,所有这些通常都是在您收到来自客户采购系统的 OrderRequest 后在您身边生成的。

    Linq-To-XML 开始,以获取制作传出 cXML 的示例(创建 XML 树部分)。将该示例与这段代码结合起来:

    StringBuilder output = new StringBuilder();
    
    XmlWriterSettings objXmlWriterSettings = new XmlWriterSettings();
    objXmlWriterSettings.Indent = true;
    objXmlWriterSettings.NewLineChars = Environment.NewLine;
    objXmlWriterSettings.NewLineHandling = NewLineHandling.Replace;
    objXmlWriterSettings.NewLineOnAttributes = false;
    objXmlWriterSettings.Encoding = new UTF8Encoding();
    
    using (XmlWriter objXmlWriter = XmlWriter.Create(output, objXmlWriterSettings)) {
        XElement root = new XElement("Root",
            new XElement("Child", "child content")
        );
        root.Save(objXmlWriter);
    }
    Console.WriteLine(output.ToString());
    

    因此,此时 StringBuilder(输出)拥有您的整个 cXML,您需要将其发布到某个地方。您的 Web 应用程序项目,从 F5 开始,一个 default.aspx 页面将监听 localhost 和一些端口(您将在它打开的 URL 中看到)。另外,也许使用 VS Express for Desktop,您可以在控制台应用程序中使用上述代码,您可以使用以下代码运行该代码:

    Net.HttpWebRequest objRequest = Net.WebRequest.Create("http://localhost:12345/handler.ashx");
    
    objRequest.Method = "POST";
    objRequest.UserAgent = "Some User Agent";
    objRequest.ContentLength = output.Length;
    objRequest.ContentType = "text/xml";
    
    IO.StreamWriter objStreamWriter = new IO.StreamWriter(objRequest.GetRequestStream, System.Text.Encoding.ASCII);
    objStreamWriter.Write(output);
    objStreamWriter.Flush();
    objStreamWriter.Close();
    
    Net.WebResponse objWebResponse = objRequest.GetResponse();
    XmlReaderSettings objXmlReaderSettings = new XmlReaderSettings();
    objXmlReaderSettings.DtdProcessing = DtdProcessing.Ignore;
    XmlReader objXmlReader = XmlReader.Create(objWebResponse.GetResponseStream, objXmlReaderSettings);
    
    // Pipes the stream to a higher level stream reader with the required encoding format.  
    IO.MemoryStream objMemoryStream2 = new IO.MemoryStream();
    XmlWriter objXmlWriter2 = XmlWriter.Create(objMemoryStream2, objXmlWriterSettings);
    objXmlWriter2.WriteNode(objXmlReader, true);
    objXmlWriter2.Flush();
    objXmlWriter2.Close();
    objWebResponse.Close();
    
    // Reset current position to the beginning so we can read all below.
    objMemoryStream2.Position = 0;
    
    StreamReader objStreamReader = new StreamReader(objMemoryStream2, Encoding.UTF8);
    Console.WriteLine(objStreamReader.ReadToEnd());
    objStreamReader.Close();
    

    由于您的处理程序应该生成 cXML,您会在控制台中看到它吐出的内容。如果它吐了,你会在控制台中得到一大堆调试混乱,这当然会帮助你修复任何被破坏的东西。

    • 请原谅变量名中的冗长,这样做是为了让事情变得清晰。

    【讨论】:

    • 谢谢@MrGadget。很好的答案。我会解决它,让你知道它是怎么回事。应该是其他 cXML 新手的一个很好的参考。
    • 通过其他考虑扩展了我的答案。
    • 我正在尝试弄清楚如何在 Localhost 上进行测试。我的大脑已经麻木了,试图弄清楚如何发送一个模拟的punchoutsetuprequest,这样我就可以确保我抓住了正确的值并发送了正确的东西。你能提出任何建议吗?如果这个问题非常愚蠢,我很抱歉......我确定我在这里只见树木不见森林,这应该很容易做到。
    • 出于好奇 - 为什么将 objMemoryStream2.Position 设置为 0?以便 ReadToEnd 从 0 索引开始?如果省略该行,objStreamReader 是否会从内存流的末尾(当前位置)读取到内存流的末尾(ReadToEnd)?
    • 如果您访问 cXML 网站并下载 dtd 文件,您可以将其转换为 xsd 文件,然后使用 xsd.exe 自动生成用于设置属性的 C# 类。我在跳过一些类引用时遇到了问题(即 cXML 根节点缺少 Message 节点)。如果您想使用序列化来分解 PunchOutRequest 并构建 PunchoutOrderMessages,这是一个很好的开始。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多