首页 > 解决方案 > 如何从 MQL4 将数据发布到 C# 网络服务

问题描述

我正在尝试使用 MQL4 将 Metatrader 的历史数据发布到用 C# 编写的 Web 服务。我遇到的问题是 MQL4 中的字符串是占用 2 个字节的 Unicode,而 C# 中的字符串是 ANSI。因此看起来接收方的每个字符之间都有一个空格。

#import  "Wininet.dll"
   int InternetOpenW(string, int, string, string, int);
   int InternetOpenUrl(int, string, string, int, int, int);
   int InternetCloseHandle(int); 
   int HttpOpenRequestW(int, string, string, string, string, string& AcceptTypes[], int, int);
   bool HttpSendRequestW(int, string, int, string, int);
   int InternetConnectW(int, string, int, string, string, int, int, int);
#import
#import "kernel32.dll"
   int GetLastError(void);
#import

void SendHistory()
{
   int i,hstTotal=HistoryTotal();
   for(i=0;i<hstTotal;i++)
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
      {
         if(OrderSymbol()!="") // Skip balance statements for now
         {
            string body=GetBody();

            //--- Reset the last error code
            ResetLastError();
            // Only send newer Tickets
            if (OrderTicket() > lastOrderSent)
            {
               string headers = "Content-Type: application/x-www-form-urlencoded";
               string data = "";
               string acceptTypes[1] = {"application/json"};

               int HttpOpen = InternetOpenW(" ", 0, " ", "", 0);  
               int HttpConnect = InternetConnectW(HttpOpen, serverName, 27408, "", "", 3, 0, 0);
               int HttpRequest = HttpOpenRequestW(HttpConnect, "POST","/api/Transactions", "", "", acceptTypes, 0, 0);   
               bool result = HttpSendRequestW(HttpRequest, headers, StringLen(headers), body), StringLen(body));
               string lastError = kernel32::GetLastError();
               Print ("Last MSDN Error =: ", lastError);
               int read[1];
               Print("This is the POST result: ", result);
               InternetCloseHandle(HttpOpen);
               InternetCloseHandle(HttpRequest);            
            }          
         }
      }
   }
   return;
}
string GetBody()
{
   string bodyPart1=
     StringConcatenate("{","\"Order\"",":",OrderTicket(),",",
       "\"Time\"",":","\"",GetTimeString(OrderOpenTime()),"\"",",",
       "\"Type\"",":",OrderType(),",",
       "\"Lots\"",":",OrderLots(),",",
       "\"Symbol\"",":","\"",OrderSymbol(),"\"",",",
       "\"Price\"",":",OrderOpenPrice(),",",
       "\"StopLoss\"",":",OrderStopLoss(),",",
       "\"TakeProfit\"",":",OrderTakeProfit(),",",
       "\"CloseTime\"",":","\"",GetTimeString(OrderCloseTime()),"\"",","
       );
   string bodyPart2=
     StringConcatenate("\"ClosePrice\"",":",OrderClosePrice(),",",
       "\"Swap\"",":",OrderSwap(),",",
       "\"Profit\"",":",OrderProfit(),",",
       "\"Comment\"",":","\"",OrderComment(),"\"",",",
       "\"Commission\"",":",OrderCommission(),",",
       "\"Expiration\"",":","\"",OrderExpiration(),"\"",",",
       "\"MagicNumber\"",":",OrderMagicNumber(),",",
       "\"AccountNumber\"",":","\"",AccountNumber(),"\"",",",
       "\"Id\"",":","\"",OrderTicket(),"\"","}"
       );
   return(StringConcatenate(bodyPart1,bodyPart2));
}

在 C# 端,它看起来像这样:

// POST: api/Transactions
[ResponseType(typeof(Transaction))]
public async Task<IHttpActionResult> PostTransaction(Transaction transaction)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    db.Transactions.Add(transaction);
    try
    {
        await db.SaveChangesAsync();
    }
    catch (DbUpdateException)
    {
        if (TransactionExists(transaction.Id))
        {
            return Conflict();
        }
        else
        {
            throw;
        }
    }

    return CreatedAtRoute("DefaultApi", new { id = transaction.Id }, transaction);
}

事务类是

public class Transaction
{
    public string Id { get; set; }
    public int Order { get; set; }
    public DateTime Time { get; set; }
    public int Type { get; set; }
    public decimal Lots { get; set; }
    public string Symbol { get; set; }
    public decimal Price { get; set; }
    public decimal StopLoss { get; set; }
    public decimal TakeProfit { get; set; }
    public DateTime? CloseTime { get; set; }
    public decimal ClosePrice { get; set; }
    public decimal Swap { get; set; }
    public decimal Profit { get; set; }
    [StringLength(255)]
    public string Comment { get; set; }
    public decimal Commission { get; set; }
    public DateTime? Expiration { get; set; }
    public int MagicNumber { get; set; }
    public string AccountNumber { get; set; }
}

但由于 Unicode 与 ANSI 在字符串处理上的差异,Web Api 控制器接收到的 Transaction 对象始终为空。我尝试使用 StringToCharArray 将 Unicode 字符串转换为 ANSI,但 HttpSendRequestW 需要一个字符串作为正文参数。Wininet.dll 的 Internet*A 函数甚至不会到达 Web Api 端点,因为 URL 也是 Unicode 并且它尝试调用http: //localhost 而不是http://localhost

我无法使用 WebRequest,因为它仅限于端口 80 和 443。我的端口(至少用于测试)是 27408。

任何人都可以帮助我们完成这项工作吗?

标签: c#postasp.net-web-apimql4

解决方案


推荐阅读