从MVC Controller操作

时间:2017-04-24 21:02:01

标签: javascript c# asp.net asp.net-mvc webforms

我正在重写现有的webform以使用js库,而不是使用供应商控件和microsoft ajax工具(基本上,更新Web应用程序以使用更现代的方法)。

AS-IS页面(webform)使用服务器上的按钮单击处理程序来处理提交的数据并返回包含xml的文档,然后可以保存或打开该文档(打开它作为另一个选项卡在浏览器)。这是异步发生的。

TO-BE页面使用jquery ajax将表单提交给MVC控制器,其中几乎完全执行与服务器端回发情况相同的完整代码。我已经在浏览器中验证了调用者返回的相同数据,但是在返回之后,系统不会提示用户保存/打开 - 页面就像是什么都没发生一样。

我将把代码放在下面,但我想我只是错过了回发和ajax / controller上下文之间的一些关键差异,以提示浏览器将返回的数据识别为要保存的单独附件。我的问题是,我已经看过并尝试过如此多的临时方法,我不确定此时我做错了什么。

AS-IS服务器端处理程序 (Absd,因为SendXml()方法是生成响应的原因)

protected void btnXMLButton_Clicked(object sender, EventArgs e)
{
    //generate server side biz objects
    //formattedXml is a string of xml iteratively generated from each selected item that was posted back

    var documentStream = MemStreamMgmt.StringToMemoryStream(formattedXml);
    byte[] _documentXMLFile = documentStream.ToArray();

    SendXml(_documentXMLFile);
}

private void SendXml(byte[] xmlDoc)
{
    string _xmlDocument = System.Text.Encoding.UTF8.GetString(xmlDoc);

    XDocument _xdoc = XDocument.Parse(_xmlDocument);
    var _dcpXMLSchema = new XmlSchemaSet();
    _dcpXMLSchema.Add("", Server.MapPath(@"~/Orders/DCP.xsd"));
    bool _result = true;
    try
    {
        _xdoc.Validate(_dcpXMLSchema, null);
    }
    catch (XmlSchemaValidationException)
    {
        //validation failed raise error
        _result = false;
    }
    // return error message
    if (!_result)
    {
        //stuff to display message
        return;
    }

    // all is well .. download xml file
    Response.ClearContent();
    Response.Clear();
    Response.ContentType = "text/plain";
    Response.AddHeader("Content-disposition", "attachment; filename=" +   "XMLOrdersExported_" + string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}.xml", DateTime.Now));
    Response.BinaryWrite(xmlDoc);
    Response.Flush();
    Context.ApplicationInstance.CompleteRequest();
    Response.End();
}

TO-BE(使用jquery提交控制器操作) 客户端代码:按钮单击处理程序:

queueModel.getXmlForSelectedOrders = function () {
    //create form to submit
    $('body').append('<form id="formXmlTest"></form>');

    //submit handler
    $('#formXmlTest').submit(function(event) {
        var orderNbrs = queueModel.selectedItems().map(function (e) { return e.OrderId() });
        console.log(orderNbrs);
        var ordersForXml = orderNbrs;
        var urlx = "http://localhost:1234/svc/OrderServices/GetXml";
        $.ajax({
            url: urlx,
            type: 'POST',
            data: { orders: ordersForXml },
            dataType: "xml",
            accepts: {
                xml: 'application/xhtml+xml',
                text: 'text/plain'
            }
        }).done(function (data) {
              /*Updated per comments */
            console.log(data);

            var link = document.createElement("a");
            link.target = "blank";
            link.download = "someFile";//data.name
            console.log(link.download);
            link.href = "http://localhost:23968/svc/OrderServices/GetFile/demo.xml";//data.uri;
            link.click();
        });
        event.preventDefault();
    });
    $('#formXmlTest').submit();
};

//Updated per comments
/* 
[System.Web.Mvc.HttpPost]
public void GetXml([FromBody] string[] orders)
{
    //same code to generate xml string
    var documentStream = MemStreamMgmt.StringToMemoryStream(formattedXml);
    byte[] _documentXMLFile = documentStream.ToArray();

    //SendXml(_documentXMLFile);
    string _xmlDocument = System.Text.Encoding.UTF8.GetString(_documentXMLFile);

    XDocument _xdoc = XDocument.Parse(_xmlDocument);
    var _dcpXMLSchema = new XmlSchemaSet();
    _dcpXMLSchema.Add("", Server.MapPath(@"~/Orders/DCP.xsd"));
    bool _result = true;
    try
    {
        _xdoc.Validate(_dcpXMLSchema, null);
    }
    catch (XmlSchemaValidationException)
    {
        //validation failed raise error
        _result = false;
    }

    Response.ClearContent();
    Response.Clear();
    Response.ContentType = "text/plain";
    Response.AddHeader("Content-disposition", "attachment; filename=" + "XMLOrdersExported_" + string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}.xml", DateTime.Now));
    Response.BinaryWrite(_documentXMLFile);
    Response.Flush();
    //Context.ApplicationInstance.CompleteRequest();
    Response.End();
    }
}*/
[System.Web.Mvc.HttpPost]
public FileResult GetXmlAsFile([FromBody] string[] orders)
{
    var schema = Server.MapPath(@"~/Orders/DCP.xsd");
    var formattedXml = OrderXmlFormatter.GenerateXmlForSelectedOrders(orders, schema);
    var _result = validateXml(formattedXml.DocumentXmlFile, schema);

    // return error message
    if (!_result)
    {
        const string message = "The XML File(s) are not valid! Please check with your administrator!.";
        return null;
    }
    var cd = new System.Net.Mime.ContentDisposition
    {
        FileName = "blargoWargo.xml",
        Inline = false
    };
    System.IO.File.WriteAllBytes(Server.MapPath("~/temp/demo.xml"),formattedXml.DocumentXmlFile);
    return File(formattedXml.DocumentXmlFile,MediaTypeNames.Text.Plain,"blarg.xml");
}

[System.Web.Mvc.HttpGet]
public FileResult GetFile(string fileName)
{
    var cd = new System.Net.Mime.ContentDisposition
    {
        // for example foo.bak
        FileName = fileName,
        Inline = false
    };
    Response.AppendHeader("Content-Disposition", cd.ToString());
    var fName = !string.IsNullOrEmpty(fileName)?fileName:"demo.xml";
    var fArray = System.IO.File.ReadAllBytes(Server.MapPath("~/temp/" + fName));
    System.IO.File.Delete(Server.MapPath("~/temp/" + fName));
    return File(fArray, MediaTypeNames.Application.Octet);
}

更新: 我只是将AS-IS / TO-BE并排放置,并且在dev工具中验证了唯一的区别(至少就开发工具显示而言)是TO-BE的ACCEPT:标头是:

application / xhtml + xml, / ; Q = 0.01

而AS-IS的标题是

text / html,application / xhtml + xml,image / jxr, /

更新II 我找到了一个解决方法,使用带有超链接的两步过程。这是一个解决方案的笨蛋,但正如我所怀疑的那样,显然在进行ajax调用时(至少是jQuery ajax调用,而不是直接的XmlHttpRequest),不可能触发打开/保存对话框。因此,在POST步骤中,我创建并保存所需的文件,然后在GET步骤中(使用动态创建的链接)我将文件发送到客户端并从服务器中删除它。我暂时没有回答这个问题,希望能够理解差异的人可以解释为什么你不能在正常的ajax调用过程中检索文件。

0 个答案:

没有答案