What could be the reason that my custom REST seria

2019-09-05 14:32发布

问题:

Both methods MyBehavior::CreateSerializer() are not called of some reason, but ReplaceBehavior() method is working. It is changing default behavior with my custom one.

Do someone know where could be the problem?

The point is to write custom REST WCF serializer that should generate non-XML text format result.

  public class MySerializerFormatAttribute : Attribute, IOperationBehavior
   {
      public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
      {
      }

      public void Validate(OperationDescription description)
      {
      }

      private static void ReplaceBehavior(OperationDescription description)
      {
         DataContractSerializerOperationBehavior dcsOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
         if (dcsOperationBehavior != null)
         {
            int idx = description.Behaviors.IndexOf(dcsOperationBehavior);
            description.Behaviors.Remove(dcsOperationBehavior);
            description.Behaviors.Insert(idx, new MyBehavior(description));
         }
      }

      public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
      {
         ReplaceBehavior(description);
      }


      public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
      {
         ReplaceBehavior(description);
      }
   };

   public class MySerializer : XmlObjectSerializer
   {
      public override bool IsStartObject(XmlDictionaryReader reader)
      {
         throw new NotImplementedException();
      }

      public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
      {
         throw new NotImplementedException();
      }

      public override void WriteEndObject(XmlDictionaryWriter writer)
      {
         throw new NotImplementedException();
      }

      public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
      {
         throw new NotImplementedException();
      }

      public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
      {
         throw new NotImplementedException();
      }
   }

   // Custom Web service behaviour that passes custom serializer
   public class MyBehavior : DataContractSerializerOperationBehavior
   {
      private static MySerializer serializer = new MySerializer();

      public MyBehavior(OperationDescription operationDescription) : base(operationDescription) 
      { 
      }

      public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
      {
         return MyBehavior.serializer;
      }

      public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
      {
         return MyBehavior.serializer;
      }
   }

回答1:

That's totally ignored in the System.ServiceModel.Web world. Checkout DataContractSerializerOperationBehavior in Reflector. You'll see "System.ServiceModel.Dispatcher.DataContractJsonSerializerOperationBehavior". If you run Analyze (Used By) on that, you will then see the horror: DataContractJsonSerializerOperationFormatter is instantiating DataContractJsonSerializerOperationBehavior itself. So... nothing you add will do anything.

What really sucks is that the operation formatter and everything else around it is internal. WCF is extremely extensible, but the dudes who built System.ServiceModel.Web seem to hate extensibility. I run into some sealed/internal roadblock at least once a week. Almost none of my SOAP customizations work in the JSON world.