65

WebMethod我从a返回的每个对象ScriptService都被包装到一个 JSON 对象中,其中的数据位于名为 的属性中d。没关系。但我不希望将附加__type属性提供给客户端,因为我使用 jQuery 进行手动处理。

可能吗?

4

17 回答 17

40

我发现,如果我将我的类的默认构造函数设为我的 web 方法返回除 public 以外的任何内容,它不会序列化该__type:ClassName部分。

您可能想要声明您的默认构造函数protected internal ClassName() { }

于 2009-04-22T16:09:14.660 回答
25

John 的解决方案对我不起作用,因为我返回的类型位于单独的 DLL 中。我可以完全控制那个 DLL,但是如果构造函数是内部的,我就不能构造我的返回类型。

我想知道返回类型是否是库中的公共类型甚至可能是原因 - 我已经做了很多 Ajax 并且以前没有见过这个。

快速测试:

  • 暂时将返回类型声明移至 App_Code。还是要__type连载。

  • 同上并为每个 JM 应用受保护的内部构造函数。这行得通(所以他得到了投票)。

奇怪的是,我没有得到__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)
于 2010-10-01T13:33:31.940 回答
16

我一直在使用 .NET 4 WCF 服务尝试其中一些建议,但它们似乎不起作用 - JSON 响应仍然包含 __type。

我发现删除类型提示的最简单方法是将端点行为从 enableWebScript 更改为 webHttp。

    <behavior name="MapData.MapDataServiceAspNetAjaxBehavior">
      <webHttp />
    </behavior>

如果您使用的是 ASP.NET AJAX 客户端,则需要默认 enableWebScript 行为,但如果您使用 JavaScript 或 jQuery 操作 JSON,那么 webHttp 行为可能是更好的选择。

于 2010-12-19T11:18:52.207 回答
12

如果您使用的是ServiceStack.Text JSON Serializer,您只需要:

JsConfig.ExcludeTypeInfo = true;

此功能在v2.28中自动添加回,但上面的代码将其排除在序列化之外。您还可以通过以下方式更改此行为Type

JsConfig<Type>.ExcludeTypeInfo = true;
于 2012-10-12T16:51:58.227 回答
4

我想我已经缩小了神秘出现的“__type”的根本原因!

这是一个可以重新创建问题的示例。

[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 类作为参数.... __type 将被添加到调用另一个方法返回的 JSON 中:MyMethodB()。

虽然方法不同!!

我的理论如下:

  1. 在编写这样的 Web 服务时,Microsoft 的代码会自动为您连接 JSON 序列化/反序列化行为,因为您使用了正确的属性,例如 [WebMethod] 和 [ScriptService]。
  2. 当这个自动魔术 Microsoft 代码执行时,它会找到一个将 Cat 类作为参数的方法。
  3. 它数字......哦......好吧......好吧,因为我将从JSON接收一个Cat对象......因此......如果我从当前Web服务中的任何方法返回一个Cat对象作为JSON类...我会给它一个 __type 属性,以便稍后在反序列化回 C# 时很容易识别。
  4. 呐~哈哈哈哈……

重要外卖注意事项

您可以避免 __type 属性出现在生成的 JSON 中,方法是避免将有问题的类(在我的例子中为 Cat)作为 Web 服务中任何 WebMethods 的参数。因此,在上面的代码中,只需尝试修改 MyMethodA() 以删除 Cat 参数。这会导致生成 __type 属性。

于 2012-10-17T22:31:07.293 回答
3

为 JavaScriptTypeResolver 传入 null 并且 __type 不会被序列化

JavaScriptSerializer serializer = new JavaScriptSerializer(null);
string json = serializer.Serialize(foo);
于 2011-11-24T03:02:57.857 回答
2

我不确定这是一个好的解决方案,但是如果您使用Json.net 库,您可以通过添加[JsonIgnore]属性来忽略某些属性。

于 2010-03-03T19:54:50.043 回答
2

除了 John Morrison 对DataContract 类中的内部受保护的内部构造函数的建议之外,它对 Web 服务和大多数 WCF 都非常有效,您可能需要在 web.config 文件中进行额外的更改。而不是用于您的端点行为的<enableWebScript/>元素<webHttp/>,例如:

<endpointBehaviors>
  <behavior name="MyServiceEndpoint">
    <webHttp/>
  </behavior>
</endpointBehaviors>
于 2012-10-03T19:18:41.693 回答
2

我的 2 美分,但在当天很晚:正如其他人所提到的,似乎有两种方法可以防止“__type”属性:

a) 保护无参数构造函数

b) 避免将类作为参数传递给 Web 方法

如果您永远不需要将类作为参数传递,那么您可以使构造函数“受保护的内部”。如果您需要创建一个空对象,请添加工厂方法或其他带有虚拟参数的构造函数。

但是,如果您需要将类作为参数传递给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() { }
}

任何需要接受 MyClass 的 web 方法然后使用 MyClassForParams 代替:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public MyClass DoSomething(MyClassForParams someObject)
{
    // Do something with someObject
    ...
    // Maybe return a MyClass object
    ...
}
于 2015-03-08T10:21:25.100 回答
1

不要使用 [Serializable] 属性。

以下应该做到这一点

JavaScriptSerializer ser = new JavaScriptSerializer(); 字符串 json = ser.Serialize(objectClass);

于 2009-06-03T08:32:00.047 回答
1

线程有点晚了,但这里有。

当添加到 json 字符串的属性是 List<T> 时,我们遇到了同样的问题。我们所做的是添加另一个属性,它是一个 T 数组,类似于。

前。

[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 { }
}

虽然不是一个理想的解决方案,但它可以解决问题。

于 2012-05-22T05:09:05.130 回答
1

这是一种解决方法

    [WebMethod]
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
    public void Status()
    {
        MyObject myObject = new MyObject(); // Your class here
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(myObject);

        HttpContext.Current.Response.Write(json);
    }
于 2018-11-05T20:52:44.317 回答
0

这应该解决它。

在 System.WebExtensions.dll 中 JavaScriptSerializer 的私有 SerializeValue 方法中,如果可以解析 __type,则将其添加到内部字典中。

从反射器:

private void SerializeValue(object o, StringBuilder sb, int depth, Hashtable objectsInUse)
{
    if (++depth > this._recursionLimit)
    {
        throw new ArgumentException(AtlasWeb.JSON_DepthLimitExceeded);
    }
    JavaScriptConverter converter = null;
    if ((o != null) && this.ConverterExistsForType(o.GetType(), out converter))
    {
        IDictionary<string, object> dictionary = converter.Serialize(o, this);
        if (this.TypeResolver != null)
        {
            string str = this.TypeResolver.ResolveTypeId(o.GetType());
            if (str != null)
            {
                dictionary["__type"] = str;
            }
        }
        sb.Append(this.Serialize(dictionary));
    }
    else
    {
        this.SerializeValueInternal(o, sb, depth, objectsInUse);
    }
}

如果无法确定类型,序列化仍将继续,但类型将被忽略。好消息是,由于匿名类型继承 getType() 并且返回的名称是由编译器动态生成的,因此 TypeResolver 为 ResolveTypeId 返回 null 并且“__type”属性随后被忽略。

为了以防万一,我还采用了内部构造函数的 John Morrison 的建议,尽管仅使用这种方法,我仍然在我的 JSON 响应中获得 __type 属性。

//Given the following class
[XmlType("T")]
public class Foo
{
    internal Foo()
    {

    }

    [XmlAttribute("p")]
    public uint Bar
    {
        get;
        set;
    }
}

[WebService(Namespace = "http://me.com/10/8")]
[System.ComponentModel.ToolboxItem(false)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class MyService : System.Web.Services.WebService
{

    //Return Anonymous Type to omit the __type property from JSON serialization
    [WebMethod(EnableSession = true)]
    [System.Web.Script.Services.ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
    public object GetFoo(int pageId)
    {
        //Kludge, returning an anonymois type using link, prevents returning the _type attribute.
        List<Foo> foos = new List<Foo>();
        rtnFoos.Add( new Foo(){
            Bar=99
        }};

        var rtn = from g in foos.AsEnumerable()
                   select g;

        return rtn;
    }
}

注意: 我使用的是继承的 JSON 类型转换器,它从序列化类型中读取 XML 序列化属性以进一步压缩 JSON。感谢CodeJournal。奇迹般有效。

于 2010-08-09T21:50:38.363 回答
0

除了@sean 对 using 的回答JavaScriptSerializer

当使用 JavaScriptSerializer 并标记方法的ResponseFormat = WebMessageFormat.Json时,结果响应具有双 JSON 编码加上如果结果响应是string,它将被放在双引号之间。

为避免这种情况,请使用此出色答案中的解决方案将内容类型定义为 JSON(覆盖)并将JavaScriptSerializer.

来自上述答案的代码示例:

public Stream GetCurrentCart()
{
    //Code ommited
    var j = new { Content = response.Content, Display=response.Display,
                  SubTotal=response.SubTotal};
    var s = new JavaScriptSerializer();
    string jsonClient = s.Serialize(j);
    WebOperationContext.Current.OutgoingResponse.ContentType =
        "application/json; charset=utf-8";
    return new MemoryStream(Encoding.UTF8.GetBytes(jsonClient));
}

JavaScriptSerializer在默认情况下不引用的System.Web.Script.Serialization命名空间中。System.Web.Extensions.dll

于 2019-03-27T15:42:56.293 回答
0

您可以使用创建自己的返回类型来发送响应。并且在发送响应时使用对象作为返回类型 .so _type 属性将被忽略。

于 2020-09-15T07:13:52.590 回答
-1
var settings = new DataContractJsonSerializerSettings();
settings.EmitTypeInformation = EmitTypeInformation.Never;
DataContractJsonSerializer serializerInput = new DataContractJsonSerializer(typeof(Person), settings);
var ms = new MemoryStream();
serializerInput.WriteObject(ms, personObj);
string newRequest = Encoding.UTF8.GetString(ms.ToArray());
于 2019-08-05T00:45:22.260 回答
-7

这有点 hack,但这对我有用(使用 C#):

s = (JSON string with "__type":"clsname", attributes)
string match = "\"__type\":\"([^\\\"]|\\.)*\",";
RegEx regex = new Regex(match, RegexOptions.Singleline);
string cleaned = regex.Replace(s, "");

适用于两者[DataContract][DataContract(Namespace="")]

于 2011-06-14T20:38:40.783 回答