如何将 HTTP 请求标头添加到 Silverlight RIA 请求

发布于 2024-12-20 09:08:56 字数 252 浏览 6 评论 0原文

我需要为 Silverlight 应用程序发出的每个 RIA 服务请求传递一个 HTTP 标头。标头的值需要来自应用程序实例,而不是来自 cookie。我知道这可以通过将其放入 DTO 中来实现,但这不是一个选项,因为我们的许多服务调用都使用实体和更改集,因此没有基类可用于所有请求。因此,我正在寻找一种集中且安全的方法来为每个请求传回一些内容,这样开发人员就不必担心它。自定义 HTTP 标头可以正常工作,但我不知道如何拦截出站请求来设置它。

有人有什么想法我可以尝试吗?

I have a need to pass an HTTP header for each an every RIA Service request being made from a Silverlight app. The value of the header needs to come from the app instance, and not from a cookie. I know this can be accomplished by putting it in the DTOs, but it's not an option because a lot of our service calls use Entities and change sets, so there's no base class to tie into for all requests. So I'm looking for a centralized and safe means to pass something back with each request so the developers do not have to worry with it. A custom HTTP header would work fine, but I don't know how to intercept the outbound request to set it.

Anyone have any ideas I can try?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

九八野马 2024-12-27 09:08:56

在较低级别,您可以在 IClientMessageInspector 的帮助下添加 HTTP 标头。尝试从SL 论坛上的这篇文章开始。

下一步取决于您的用例。

如果标头的值对于由 DomainContext 调用的任何方法都必须相同,那么您可以使用分部类扩展上下文,为标头值添加属性并在检查器中使用该属性。

如果您需要为每个方法调用传递不同的值,则可能需要将 DomainContext 包装到另一个类中,并向上下文的每个方法添加一个参数,该参数将接受标头值并传递以某种方式交给检查员。不用说,如果没有代码生成器,这将很难。

以下是 SL 论坛针对第一个案例的改编示例:

public sealed partial class MyDomainContext
{
  public string HeaderValue { get; set; }

  partial void OnCreated()
  {
    WebDomainClient<IMyDomainServiceContract> webDomainClient = (WebDomainClient<IMyDomainServiceContract>)DomainClient;
    CustomHeaderEndpointBehavior customHeaderEndpointBehavior = new CustomHeaderEndpointBehavior(this);
    webDomainClient.ChannelFactory.Endpoint.Behaviors.Add(customHeaderEndpointBehavior);
  }
}

public class CustomHeaderEndpointBehavior : IEndpointBehavior
{
  MyDomainContext _Ctx;

  public CustomHeaderEndpointBehavior(MyDomainContext ctx)
  {
    this._Ctx = ctx;
  }      

  public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
  public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
  {
    clientRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(this._Ctx));
  }
  public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { }
  public void Validate(ServiceEndpoint endpoint) { }
}

public class CustomHeaderMessageInspector : IClientMessageInspector
{
  MyDomainContext _Ctx;

  public CustomHeaderMessageInspector(MyDomainContext ctx)
  {
    this._Ctx = ctx;
  }

  public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {}
  public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
  {
    string myHeaderName = "X-Foo-Bar";
    string myheaderValue = this._Ctx.HeaderValue;

    HttpRequestMessageProperty property = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
    property.Headers[myHeaderName] = myheaderValue;
    return null;
  }
}

On the lower level you can add HTTP headers with the help of an IClientMessageInspector. Try starting from this post on SL forum.

The next step depends on your use cases.

If the value of the header must be the same for any method called by the DomainContext, then you may just extend the context using partial class, add a property for the header value and use that property in the inspector.

If you need to pass a different value for each method call, you'd probably need to wrap your DomainContext into another class and add an argument to each method of the context that will accept the header value and pass it to the inspector somehow. Needless to say, without a code-generator this would be hard.

Here's an adapted sample from the SL forum for the first case:

public sealed partial class MyDomainContext
{
  public string HeaderValue { get; set; }

  partial void OnCreated()
  {
    WebDomainClient<IMyDomainServiceContract> webDomainClient = (WebDomainClient<IMyDomainServiceContract>)DomainClient;
    CustomHeaderEndpointBehavior customHeaderEndpointBehavior = new CustomHeaderEndpointBehavior(this);
    webDomainClient.ChannelFactory.Endpoint.Behaviors.Add(customHeaderEndpointBehavior);
  }
}

public class CustomHeaderEndpointBehavior : IEndpointBehavior
{
  MyDomainContext _Ctx;

  public CustomHeaderEndpointBehavior(MyDomainContext ctx)
  {
    this._Ctx = ctx;
  }      

  public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
  public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
  {
    clientRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(this._Ctx));
  }
  public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { }
  public void Validate(ServiceEndpoint endpoint) { }
}

public class CustomHeaderMessageInspector : IClientMessageInspector
{
  MyDomainContext _Ctx;

  public CustomHeaderMessageInspector(MyDomainContext ctx)
  {
    this._Ctx = ctx;
  }

  public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) {}
  public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
  {
    string myHeaderName = "X-Foo-Bar";
    string myheaderValue = this._Ctx.HeaderValue;

    HttpRequestMessageProperty property = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
    property.Headers[myHeaderName] = myheaderValue;
    return null;
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文