我有一个通过 HTTP POST 接收 JSON 数据的控制器。在这个控制器内部是对我从 ArcGIS 的代理的 .NET 实现中复制/粘贴的方法的调用,该代理需要连接到 ArcGIS 的服务器。为了我遇到的问题,那部分是无关紧要的。
在复制/粘贴之前,执行流程是逐行的。但是现在,在复制和粘贴之后(以及随后添加对方法的调用),我的调试执行流程到处乱跳(因为不同的线程同时进行)。我不知道为什么会这样——在我复制和粘贴的代码中,我没有看到任何与线程有关的东西。你能告诉我为什么会发生这种情况只是因为我复制/粘贴的代码似乎与多线程无关吗?
这是我的控制器代码,它调用我复制/粘贴的方法:
[HttpPost]
public void PostPicture(HttpRequestMessage msg)
{
HttpContext context = HttpContext.Current;
ProcessRequest(context);
...
这是我从 ArcGIS 复制和粘贴的代码(对不起,它很长):
public void ProcessRequest(HttpContext context)
{
HttpResponse response = context.Response;
System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(context.Request.Url);
req.Method = context.Request.HttpMethod;
req.ServicePoint.Expect100Continue = false;
// Set body of request for POST requests
if (context.Request.InputStream.Length > 0)
{
byte[] bytes = new byte[context.Request.InputStream.Length];
context.Request.InputStream.Read(bytes, 0, (int)context.Request.InputStream.Length);
req.ContentLength = bytes.Length;
string ctype = context.Request.ContentType;
if (String.IsNullOrEmpty(ctype))
{
req.ContentType = "application/x-www-form-urlencoded";
}
else
{
req.ContentType = ctype;
}
using (Stream outputStream = req.GetRequestStream())
{
outputStream.Write(bytes, 0, bytes.Length);
}
}
// Send the request to the server
System.Net.WebResponse serverResponse = null;
try
{
serverResponse = req.GetResponse();
}
catch (System.Net.WebException webExc)
{
response.StatusCode = 500;
response.StatusDescription = webExc.Status.ToString();
response.Write(webExc.Response);
response.End();
return;
}
// Set up the response to the client
if (serverResponse != null)
{
response.ContentType = serverResponse.ContentType;
using (Stream byteStream = serverResponse.GetResponseStream())
{
// Text response
if (serverResponse.ContentType.Contains("text") ||
serverResponse.ContentType.Contains("json"))
{
using (StreamReader sr = new StreamReader(byteStream))
{
string strResponse = sr.ReadToEnd();
response.Write(strResponse);
}
}
else
{
// Binary response (image, lyr file, other binary file)
BinaryReader br = new BinaryReader(byteStream);
byte[] outb = br.ReadBytes((int)serverResponse.ContentLength);
br.Close();
// Tell client not to cache the image since it's dynamic
response.CacheControl = "no-cache";
// Send the image to the client
// (Note: if large images/files sent, could modify this to send in chunks)
response.OutputStream.Write(outb, 0, outb.Length);
}
serverResponse.Close();
}
}
response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
// Gets the token for a server URL from a configuration file
// TODO: ?modify so can generate a new short-lived token from username/password in the config file
private string getTokenFromConfigFile(string uri)
{
try
{
ProxyConfig config = ProxyConfig.GetCurrentConfig();
if (config != null)
return config.GetToken(uri);
else
throw new ApplicationException(
"Proxy.config file does not exist at application root, or is not readable.");
}
catch (InvalidOperationException)
{
// Proxy is being used for an unsupported service (proxy.config has mustMatch="true")
HttpResponse response = HttpContext.Current.Response;
response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
response.End();
}
catch (Exception e)
{
if (e is ApplicationException)
throw e;
// just return an empty string at this point
// -- may want to throw an exception, or add to a log file
}
return string.Empty;
}
}
[XmlRoot("ProxyConfig")]
public class ProxyConfig
{
#region Static Members
private static object _lockobject = new object();
public static ProxyConfig LoadProxyConfig(string fileName)
{
ProxyConfig config = null;
lock (_lockobject)
{
if (System.IO.File.Exists(fileName))
{
XmlSerializer reader = new XmlSerializer(typeof(ProxyConfig));
using (System.IO.StreamReader file = new System.IO.StreamReader(fileName))
{
config = (ProxyConfig)reader.Deserialize(file);
}
}
}
return config;
}
public static ProxyConfig GetCurrentConfig()
{
ProxyConfig config = HttpRuntime.Cache["proxyConfig"] as ProxyConfig;
if (config == null)
{
string fileName = GetFilename(HttpContext.Current);
config = LoadProxyConfig(fileName);
if (config != null)
{
CacheDependency dep = new CacheDependency(fileName);
HttpRuntime.Cache.Insert("proxyConfig", config, dep);
}
}
return config;
}
public static string GetFilename(HttpContext context)
{
return context.Server.MapPath("~/proxy.config");
}
#endregion
ServerUrl[] serverUrls;
bool mustMatch;
[XmlArray("serverUrls")]
[XmlArrayItem("serverUrl")]
public ServerUrl[] ServerUrls
{
get { return this.serverUrls; }
set { this.serverUrls = value; }
}
[XmlAttribute("mustMatch")]
public bool MustMatch
{
get { return mustMatch; }
set { mustMatch = value; }
}
public string GetToken(string uri)
{
foreach (ServerUrl su in serverUrls)
{
if (su.MatchAll && uri.StartsWith(su.Url, StringComparison.InvariantCultureIgnoreCase))
{
return su.Token;
}
else
{
if (String.Compare(uri, su.Url, StringComparison.InvariantCultureIgnoreCase) == 0)
return su.Token;
}
}
if (mustMatch)
throw new InvalidOperationException();
return string.Empty;
}
}
public class ServerUrl
{
string url;
bool matchAll;
string token;
[XmlAttribute("url")]
public string Url
{
get { return url; }
set { url = value; }
}
[XmlAttribute("matchAll")]
public bool MatchAll
{
get { return matchAll; }
set { matchAll = value; }
}
[XmlAttribute("token")]
public string Token
{
get { return token; }
set { token = value; }
}
}