如何将整个 http URL 传递给 asp.net API 中的存储过程?

How do I pass the whole http URL to a stored procedure in an asp.net API?

我的任务是创建一个 asp.net API 其中:

对 api 的调用示例:

https://localhost:44308/api/OrderProcessing?<?xml version="1.0"encoding="utf-8"?><Param1>abc123</Param1><Param2>5</Param2><Param3>123456</Param3>etc.. etc

我发现了很多从 asp.net 调用过程的示例,所有示例都显示 XML 节点被解析为参数以传递给存储过程:

usp_myproc @param1 =abc123, @param2  =5, @param3 =123456 etc.

我找不到如何将 xml 作为单个字符串传递,如下所示 EG

    usp_myproc @param1 =xml version="1.0"encoding="utf-8"?><Param1>abc123</Param1><Param2>5</Param2><Param3>123456</Param3>etc.. etc

到目前为止,我有以下代码,其中当然只是传递了第一个参数,例如。 usp_myproc @param1 不是整个字符串

    namespace OrderProcessingApp.Controllers
    {
        public class OrderProcessingController : ApiController
        {
            [HttpGet]
            public IHttpActionResult StockOrder(string param1)
            {
               StockFinderEntities sd = new StockFinderEntities();
               var results = sd.fn_ProcessOrder(param1).ToList();
            }
        }
    }

非常感谢收到的任何帮助

这里有很多内容需要解压缩,并且缺少一些信息,另请参阅我对您的问题的评论。虽然你的问题中有可以回答的部分,但情况远非最佳。

如果我没说错,你想要这个:

  • 一个 API 端点,它接受查询字符串完全由 XML 字符串组成的 GET 请求。
  • 在此操作方法中,将 XML 字符串传递给 SQL 用户定义函数。
  • 此函数解析 XML,执行其操作,returns 零个或多个记录。
  • 然后将这些记录作为列表返回给调用者。

首先,您必须阅读 XML。您的查询字符串似乎没有键(它直接以 ?<xml...> 开头)。这是故意的,还是在创建这个问题时的疏忽?您真的确定要从查询字符串中读取 XML 吗,或者您可以更改此设计吗?

如果您可以更改它,惯用的方法是使用查询字符串参数,然后将其绑定到您的操作方法参数:

// GET .../StockOrder?param1=42&param2=Foo&param3=Bar
public IHttpActionResult StockOrder(string param1, string param2, string param3) { ... }

假设您真的想将原始查询字符串读取为 XML,而不是单个参数:

// GET .../StockOrder?xmlString=<xml...>
public IHttpActionResult StockOrder(string xmlString) { ... }

那么你根本不需要任何参数:

// GET .../StockOrder?<xml...>
public IHttpActionResult StockOrder() 
{ 
    string xmlString = this.Request.RequestUri.Uri.Query.Value;
    ...
}

现在您有了 XML 字符串,您将把它传递给数据库中的用户定义函数。虽然 Entity Framework 会将其打包在 SQL 参数中,但至少您可以避免 SQL 此处的注入:

// GET .../StockOrder?<xml...>
public IHttpActionResult StockOrder() 
{ 
    string xmlString = this.Request.RequestUri.Uri.Query.Value;

    if (xmlString?.Length > 0)
    {
        // Remove the question mark from the start
        xmlString = xmlString.Substring(1);
    }       

    var results = sd.fn_ProcessOrder(xmlString).ToList();
    ...
}

但这还远未达到最佳状态!调用者可以传递无效的 XML,这只会被 SQL 服务器检测到,这在这个过程中已经太迟了。或者更糟的是,它可能是特制的 XML SQL 服务器会阻塞(就像 XML 炸弹),或者更糟(执行 XML 中包含的任意代码) .所以我不喜欢将 XML 形式的用户输入直接发送到 SQL 服务器,不。

最佳方式如下所示:

public class GetStockOrderModel
{
    [Required]
    public string Param1 { get; set; }

    [Required]
    public string Param2 { get; set; }

    [Required]
    public string Param3 { get; set; }
}


// GET .../StockOrder?param1=42&param2=Foo&param3=Bar
public IHttpActionResult StockOrder([FromUri] GetStockOrderModel model) 
{
    if (!ModelState.IsValid)
    {
        // ...
    }

    var records = sd.fn_ProcessOrder(model.Param1, model.Param2, model.Param3).ToList();

    var models = records.Select(o => new
    {
        FieldToReturn = o.Field1,
        OtherField = o.Field2,
        // ...
    }).ToList();

    return Ok(models);
}

在这里,您有一个模型可以绑定并执行验证,数据库函数被更改为接受实际参数而不是 XML,并返回一个与数据库分离的模型。

现在,如果您说您不能更改函数,因为其他应用程序调用它,您可能仍然可以。您调用的函数包含两部分:一部分从 XML 读取参数,另一部分使用这些参数执行查询。

所以你保留原来的函数,让它在提取参数后调用新函数。然后,您还可以使用代码中的参数调用该新函数。

实际上,您不想将用户 XML 传递到您的数据库服务器。当然,您会说,它只会被受信任方调用。但这些派对上的每个人都值得信任吗?他们从不犯错吗?

因此,如果您真的不想更改端点或函数的任何内容,并且您打算使用第四个(或第二个)代码块,请至少阅读 XML 中的字符串你的控制器,解析它,提取参数,验证它们,并从安全模板字符串或类似的东西重建 XML。

因为 ASP.NET,XML 被视为普通的旧字符串,所以您有 none 的验证或安全措施。