ScriptService
的WebMethod
返回的对象都被包装成一个JSON对象,其中数据存储在名为d
的属性中。这是可以接受的。但我不想将额外的__type
属性提供给客户端,因为我使用jQuery进行手动处理。有可能实现吗?
ScriptService
的WebMethod
返回的对象都被包装成一个JSON对象,其中数据存储在名为d
的属性中。这是可以接受的。但我不想将额外的__type
属性提供给客户端,因为我使用jQuery进行手动处理。我发现如果我将我的类的默认构造函数设置为除public以外的任何其他访问修饰符,它将不会序列化__type:ClassName
部分。
您可能希望将默认构造函数声明为protected internal ClassName() { }
由于我返回的类型在一个单独的DLL中,所以John的解决方案对我无效。我对那个DLL有完全的控制,但如果构造函数是internal,就不能构造我的返回类型。
我想知道返回类型是否是库中的公共类型甚至可能是原因-我一直在做很多Ajax,以前没有看到过这种情况。
快速测试:
将返回类型声明临时移动到App_Code中。仍然会得到__type
序列化。
重复上述步骤并按JM的建议应用protected internal构造函数。这个方法可行(所以他得到了一票)。
奇怪的是,使用泛型返回类型时我不会得到__type
:
[WebMethod]
public static WebMethodReturn<IEnumerable<FleetObserverLiteAddOns.VehicleAddOnAccountStatus>> GetAccountCredits()
对我来说 解决方案 是保留DLL中的返回类型,但将 WebMethod 的返回类型更改为 object,即:
[WebMethod]
public static object ApplyCredits(int addonid, int[] vehicleIds)
而不是
[WebMethod]
public static WebMethodReturn ApplyCredits(int addonid, int[] vehicleIds)
我尝试了一些.NET 4 WCF服务的建议,但它们似乎不起作用-JSON响应仍然包含__type。
我发现最简单的方法是将端点行为从enableWebScript更改为webHttp以删除类型提示。
<behavior name="MapData.MapDataServiceAspNetAjaxBehavior">
<webHttp />
</behavior>
如果你正在使用ASP.NET AJAX客户端,则需要使用默认的enableWebScript行为,但是如果你正在使用JavaScript或jQuery操作JSON,则webHttp行为可能更好。
enableWebScript
切换到webHttp
后,还必须指定defaultOutgoingResponseFormat="Json"
或automaticFormatSelectionEnabled="true"
。 - WynandB如果你正在使用ServiceStack.Text JSON序列化器,你只需要:
JsConfig.ExcludeTypeInfo = true;
这个功能在 v2.28 版本中自动添加回来了,但上面的代码将其排除在序列化之外。你也可以通过 Type
来更改此行为:
JsConfig<Type>.ExcludeTypeInfo = true;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Test : System.Web.Services.WebService
{
public class Cat
{
public String HairType { get; set; }
public int MeowVolume { get; set; }
public String Name { get; set; }
}
[WebMethod]
public String MyMethodA(Cat cat)
{
return "return value does not matter";
}
[WebMethod]
public Cat MyMethodB(String someParam)
{
return new Cat() { HairType = "Short", MeowVolume = 13, Name = "Felix the Cat" };
}
}
这里是关键部分!
仅仅因为MyMethodA()在同一个.asmx文件中存在并且以Cat类作为参数,调用另一个方法MyMethodB()返回的JSON中就会添加__type。
即使它们是不同的方法!!
我的理论如下:
重要的收获笔记
通过避免将相关类(在我的情况下是Cat)作为WebMethods中的任何参数来避免在生成的JSON中出现__type属性。因此,在上面的代码中,只需尝试修改MyMethodA()以删除Cat参数即可。这将导致__type属性不被生成。
以下是我的建议,虽然有些晚:正如其他人所提到的,似乎有两种方法可以防止 "__type" 属性:
a) 保护无参数构造函数
b) 避免将类作为参数传递给 Web 方法
如果您永远不需要将类作为参数传递,则可以将构造函数设置为 "protected internal"。如果您需要创建一个空对象,则添加一个工厂方法或者其他带有虚拟参数的构造函数。
但是,如果您需要将类作为参数传递给 Web 方法,则会发现,如果无参数构造函数受到保护(即 ajax 调用失败,可能是因为传入的 json 数据无法反序列化成您的类),这将无法工作。
这正是我的问题,所以我不得不使用 (a) 和 (b) 的组合:保护无参数构造函数,并创建一个仅用于 Web 方法参数的虚拟派生类。例如:
public class MyClass
{
protected internal MyClass() { }
public MyClass(Object someParameter) { }
...
}
// Use this class when we need to pass a JSON object into a web method
public class MyClassForParams : MyClass
{
public MyClassForParams() : base() { }
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public MyClass DoSomething(MyClassForParams someObject)
{
// Do something with someObject
...
// Maybe return a MyClass object
...
}
如果JavaScriptTypeResolver传入null,则不会序列化__type。
JavaScriptSerializer serializer = new JavaScriptSerializer(null);
string json = serializer.Serialize(foo);
除了John Morrison关于DataContract类中< strong>内部或< strong>受保护的内部构造函数的建议,这个建议非常适用于Web服务和大多数WCF操作,你可能需要在web.config文件中做出额外的更改。
为了使您的端点行为生效,请使用<webHttp/>
元素而不是<enableWebScript/>
元素,例如:
<endpointBehaviors>
<behavior name="MyServiceEndpoint">
<webHttp/>
</behavior>
</endpointBehaviors>
我不确定这是一个好的解决方案,但如果你使用Json.net库,你可以通过添加[JsonIgnore]属性来忽略一些属性。
[DataMember]
public List<Person> People { get; set; }
之后。
public List<Person> People { get; set; }
[DataMember(Name = "People")]
public Person[] Persons {
get {
return People.ToArray();
}
private set { }
}
虽然不是理想的解决方案,但它能解决问题。