C# 难以从android应用程序将复杂的JSON对象传递到RESTful服务
我对android->JSON->RESTful WCF webserive架构的实现有一个问题。我主要来自基于C模式的背景,因此很难理解android架构。我设计C webservice的方式是使用一个完整的模型名称空间,将所有业务对象(如User、UserProfile、UserSearchCriteria、UserPhoto等)定义为CLR对象 我已经使用RESTful模型通过WCF公开了我的webservice接口,并结合了我习惯使用的请求/响应模式。RESTWeb方法的一个示例如下所示C# 难以从android应用程序将复杂的JSON对象传递到RESTful服务,c#,android,json,web-services,wcf,C#,Android,Json,Web Services,Wcf,我对android->JSON->RESTful WCF webserive架构的实现有一个问题。我主要来自基于C模式的背景,因此很难理解android架构。我设计C webservice的方式是使用一个完整的模型名称空间,将所有业务对象(如User、UserProfile、UserSearchCriteria、UserPhoto等)定义为CLR对象 我已经使用RESTful模型通过WCF公开了我的webservice接口,并结合了我习惯使用的请求/响应模式。RESTWeb方法的一个示例如下所示
[OperationContract]
[WebInvoke(
Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/GetSeeds"
)]
GetSeedsResponse GetSeeds(GetSeedsRequest request);
响应对象
[DataContract]
public class GetSeedsResponse
{
public GetSeedsResponse(List<Seed> seeds)
{
Seeds = seeds;
}
[DataMember]
public List<Seed> Seeds { get; set; }
}
注意:我的所有请求对象都继承自我自己的自定义基本请求对象,该对象仅为它们提供一个用于身份验证的公共头,如下所示,我不确定这是否是处理身份验证的最佳方法,但这是我熟悉的,所以我现在已经这样做了
[DataContract]
public abstract class BaseRequest
{
[DataMember]
public Header Header { get; set; }
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.2022")]
[System.SerializableAttribute]
[System.Diagnostics.DebuggerStepThroughAttribute]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:MyStory:Web:Services:ServiceModel:Headers")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:MyStory:Web:Services:ServiceModel:Headers", IsNullable=true)]
public class Header
{
public int UserId { get; set; }
public string SessionToken { get; set; }
}
到目前为止,我已经在AsyncTask后台工作程序中使用以下代码成功地从android调用了RESTful webmethod
protected ArrayList<Seed> doInBackground(String... params)
{
try
{
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(SERVICE_URI);
post.setHeader("Accept", "application/json");
post.setHeader("Content-type", "application/json");
JSONObject data = new JSONObject();
data.put("UserId", 1);
data.put("NumberToTake", 10);
data.put("StartPosition", 0);
StringEntity entity = new StringEntity(data.toString());
post.setEntity(entity);
HttpResponse response = client.execute(post);
}
...
}
但这无法处理一般的错误请求异常,webservice甚至没有输入webmethod。我在第1行设置了一个断点,该断点在没有标头的情况下被命中,但在包含标头的情况下不会被命中,因此,我假设我没有正确理解JSON或在请求对象中传递嵌入对象的方式
[DataContract]
public class GetSeedsRequest : BaseRequest
{
public GetSeedsRequest(int userId, int numberToTake, int startPosition)
{
NumberToTake = numberToTake;
StartPosition = startPosition;
UserId = userId;
}
[DataMember]
public int NumberToTake { get; set; }
[DataMember]
public int StartPosition { get; set; }
[DataMember]
public int UserId { get; set; }
}
2我的整个架构方法是否正确?为每个web服务调用手动构造数组索引的请求和响应似乎相当费力,而且容易出错。我应该如何构建我的项目,为我的Web服务想要接受作为参数或作为响应对象返回的所有CLR对象创建匹配的android对象?JSON还有很多我不知道应该使用的功能吗?对于这些请求,我是否需要为可能进行的每个web服务调用创建定制的单个AsyncTask对象?我的应用程序将调用大约40种不同的web方法,这是否意味着40个AsyncTask对象保存在我代码库的某个包中?我正在努力找出最佳实践,设计一个具有相当数量web服务交互的大小合适的应用程序。如果有人有任何书籍或教程可以推荐,这些书籍或教程涉及到android项目设计的最佳实践、我的场景的架构,那么我将非常感激
为帖子的长度道歉将Android端与Windows服务器端分离。我们使用JSON和REST的原因是它们与系统无关。不要担心窗户侧的结构。相反,关注JSON请求对服务器的作用,并关注在Android上创建JSON 首先,获得一个类似REST的客户机,并弄清楚REST调用是什么样子的,JSON主体是什么样子的 然后,想一想如何让Android发送这个身体 最后,找出如何让Android以编程方式生成JSON主体。对于最后一个,我强烈推荐。它将允许您使用更高级别的对象,而不是手动构建JSON。如果您使用JSON主体更新请求,我将使用如何在Gson中生成响应来更新此响应
作为补充说明,我建议您查看Apache HTTP客户端,而不是Apache HTTP客户端。它的功能更加全面和强大。这完全没有必要,但它会让你的生活更轻松。谢谢你的回复,非常有帮助。就在决定什么JSON请求对服务器起作用的第一步,它应该如何看待我的WCF服务方法——我应该反序列化传递的JSON请求吗?在这种情况下,方法的签名应该是什么,字符串请求参数?例如,在我的一个请求类中,我有三个int字段和一个嵌套的复杂CLR对象,该对象本身有四个int字段和一个string字段。我是否希望将整个请求CLR对象的序列化JSON表示形式作为请求参数传递?因为您正在执行HTTP POST,所以将在POST正文中发送JSON。我对.NET服务器代码不是特别熟悉,因此我无法在服务器所期望的方面提供太多帮助,但基本上是根据GetSeedsRequest对象的性质创建的。我猜是这样的:{'NumberToTake':1,'StartPosition':2,'UserId'='jdoe'}
JSONObject header = new JSONObject();
header.put("UserId", 1);
header.put("SessionToken", "");
JSONObject data = new JSONObject();
data.put("UserId", 1);
data.put("NumberToTake", 10);
data.put("StartPosition", 0);
data.put("Header", header);