【发布时间】:2014-12-19 05:19:33
【问题描述】:
我正在根据link 中的代码编写一个网络服务器。我正在尝试从表单中获取 POST 数据,但我 无法获取该数据。网络服务器是自托管的。它基本上是一个控制面板,我可以在其中添加和编辑这些称为堆栈灯的设备。这是我的 WebServer.Run 方法:
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
Console.WriteLine("StackLight Web Server is running...");
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
// set the content type
ctx.Response.Headers[HttpResponseHeader.ContentType] = SetContentType(ctx.Request.RawUrl);
WebServerRequestData data = _responderMethod(ctx.Request);
string post = "";
if(ctx.Request.HttpMethod == "POST")
{
using(System.IO.StreamReader reader = new StreamReader(ctx.Request.InputStream, ctx.Request.ContentEncoding))
{
post = reader.ReadToEnd();
}
}
if(data.ContentType.Contains("text") || data.ContentType.Equals("application/json"))
{
// serve text/html,css,js & application/json files as UTF8
// images don't need to be served as UTF8, they don't have encodings
char[] chars = new char[data.Content.Length / sizeof(char)];
System.Buffer.BlockCopy(data.Content, 0, chars, 0, data.Content.Length);
string res = new string(chars);
data.Content = Encoding.UTF8.GetBytes(res);
}
// this writes the html out from the byte array
ctx.Response.ContentLength64 = data.Content.Length;
ctx.Response.OutputStream.Write(data.Content, 0, data.Content.Length);
}
catch (Exception ex)
{
ConfigLogger.Instance.LogCritical(LogCategory, ex);
}
finally
{
ctx.Response.OutputStream.Close();
ctx.Response.Close();
}
}, _listener.GetContext());
}
}
catch (Exception ex)
{
ConfigLogger.Instance.LogCritical(LogCategory, ex);
}
});
}
我正在使用一个名为 WebServerRequestData 的类来获取我的页面、css、javascript 和图像,以便我可以为它们提供服务。该类如下所示:
public class WebServerRequestData
{
// Raw URL from the request object
public string RawUrl { get; set; }
// Content Type of the file
public string ContentType { get; set; }
// A byte array containing the content you need to serve
public byte[] Content { get; set; }
public WebServerRequestData(string data, string contentType, string rawUrl)
{
this.ContentType = contentType;
this.RawUrl = rawUrl;
byte[] bytes = new byte[data.Length * sizeof(char)];
System.Buffer.BlockCopy(data.ToCharArray(), 0, bytes, 0, bytes.Length);
this.Content = bytes;
}
public WebServerRequestData(byte[] data, string contentType, string rawUrl)
{
this.ContentType = contentType;
this.RawUrl = rawUrl;
this.Content = data;
}
}
这是我的表格:
public static string EditStackLightPage(HttpListenerRequest request)
{
// PageHeadContent writes the <html><head>...</head> stuf
string stackLightPage = PageHeadContent();
// start of the main container
stackLightPage += ContainerDivStart;
string[] req = request.RawUrl.Split('/');
StackLightDevice stackLight = Program.StackLights.First(x => x.Name == req[2]);
stackLightPage += string.Format("<form action='/edit/{0}/update' method='post' enctype='multipart/form-data'>", stackLight.Name);
stackLightPage += string.Format("Stack Light<input type='text' id='inputName' value='{0}'>", stackLight.Name);
stackLightPage += string.Format("IP Address<input type='text' id='inputIp' value='{0}'>", stackLight.Ip);
stackLightPage += string.Format("Port Number<input type='text' id='inputPort' value='{0}'>", stackLight.Port);
stackLightPage += "<button type='submit'>Update</button>";
stackLightPage += "</form>";
// end of the main container
stackLightPage += ContainerDivEnd;
stackLightPage += PageFooterContent();
return stackLightPage;
}
只有 3 个字段:用于写入某些安全灯的自定义类的名称、IP 和端口。它是从另一个类中的 SendResponse 方法调用的。
private static WebServerRequestData SendResponse(HttpListenerRequest request)
这是我的表单被调用的部分,编辑 url 的一个例子是localhost:8080/edit/stackLight-Name,更新是localhost:8080/edit/stackLight-Name/update。这是检查 rawurl 是否包含这些路由的代码:
if(request.RawUrl.Contains("edit"))
{
if (request.RawUrl.Contains("update"))
{
// get form data from the edit page and return to the edit
_resultString = WebServerHtmlContent.EditStackLightPage(request);
_data = new WebServerRequestData(_resultString, "text/html", request.RawUrl);
return _data;
}
_resultString = WebServerHtmlContent.EditStackLightPage(request);
_data = new WebServerRequestData(_resultString, "text/html", request.RawUrl);
return _data;
}
这是我处理我的请求的地方。它有一些基于 HttpListenerRequest 对象 RawUrl 属性的 if 语句。我正在尝试获取我的表单数据。在该部分:
if(ctx.Request.HttpMethod == "POST")
{
using(System.IO.StreamReader reader = new StreamReader(ctx.Request.InputStream, ctx.Request.ContentEncoding))
{
post = reader.ReadToEnd();
}
}
我能够获得 InputStream 但我没有获得表单数据。这是我得到的数据:"------WebKitFormBoundaryAGo7VbCZ2YC79zci--\r\n"
输入流中不应该有我的表单数据吗?
我在 InputStream 的表单域中没有看到任何数据。我尝试过使用application/x-www-form-urlencoded,但这会从 ctx.Request 返回一个 null InputStream。 (ctx 是我的 HttpListenerContext 对象)。
我阅读了有关使用 multipartform 和 application/x-www-form-urlencoded 的信息,并尝试了它们。
到目前为止,多部分表单给了我数据(即使它不是表单数据),而另一个没有。
我想我已经接近让我的表单数据显示出来了。我只是卡在这一点上。我不知道该怎么办。
另外,我现在正在stackoverflow阅读这篇类似的帖子
编辑: 从该链接阅读后,我已将我的 Web 服务器运行方法更改为以下内容:
try
{
// set the content type
WebServerRequestData data = _responderMethod(ctx.Request);
string post = "";
if(ctx.Request.HttpMethod == "POST")
{
data.ContentType = ctx.Request.ContentType;
post = GetRequestPostData(ctx.Request);
}
ctx.Response.ContentLength64 = data.OutputBuffer.Length;
ctx.Response.OutputStream.Write(data.OutputBuffer, 0, data.OutputBuffer.Length);
}
这是GetRequestPostData()方法:
private static string GetRequestPostData(HttpListenerRequest request)
{
if (!request.HasEntityBody)
return null;
using(System.IO.Stream body = request.InputStream)
{
using(System.IO.StreamReader reader = new StreamReader(body, request.ContentEncoding))
{
return reader.ReadToEnd();
}
}
}
我仍然只是收到"------WebKitFormBoundaryjiSulPEnvWX7MIeq--\r\n"
【问题讨论】:
标签: c# webserver http-post httplistener httplistenerrequest