问题描述
我确实有一种情况,我必须使用Web服务将一些数据发送到D365。我已经看过https://docs.microsoft.com/en-us/biztalk/core/step-3d-enabling-biztalk-server-to-send-and-receive-messages-from-salesforce教程,了解如何使用具有OAuth安全功能的Web服务。基于此,我为WCF-Web-Http适配器开发了自定义行为。虽然出现以下错误:
System.NullReferenceException:对象引用未设置为对象的实例。 服务器堆栈跟踪: 在D365.BizTalk.Adapter.Behaviors.D365RESTSecurityBehavior.BeforeSendRequest(消息和请求,IClientChannel通道)处 在System.ServiceModel.dispatcher.ImmutableClientRuntime.BeforeSendRequest(ProxyRpc&rpc) 在System.ServiceModel.Channels.ServiceChannel.PrepareCall(ProxyOperationRuntime操作,布尔单向,ProxyRpc&rpc) 在System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.Begin() 在System.ServiceModel.Channels.ServiceChannel.BeginCall处(字符串操作,布尔单向,ProxyOperationRuntime操作,Object [] ins,TimeSpan超时,AsyncCallback回调,Object asyncState) 在System.ServiceModel.Channels.ServiceChannel.BeginRequest(消息,TimeSpan超时,AsyncCallback回调,对象状态) 在System.ServiceModel.Channels.ServiceChannel.BeginRequest(消息,AsyncCallback回调,对象状态) 异常重新抛出为[0]: 在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg) 在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&msgData,Int32类型) 在System.ServiceModel.Channels.IRequestChannel.BeginRequest(消息,AsyncCallback回调,对象状态) 在Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient
2.SendRequestMessage(IBaseMessage bizTalkMessage,IRequestChannel channel) at Microsoft.BizTalk.Adapter.Wcf.Runtime.WcfClient
2.SendMessage(IBaseMessage bizTalkMessage)中
- class D365OAuthToken
namespace D365.BizTalk.Adapter.Behaviors
{
public class D365OAuthToken
{
public string id { get; set; }
public string issued_at { get; set; }
public string refresh_token { get; set; }
public string instance_url { get; set; }
public string signature { get; set; }
public string access_token { get; set; }
}
}
- class D365RESTSecurityBehavior
namespace D365.BizTalk.Adapter.Behaviors
{
public class D365RESTSecurityBehavior : IClientMessageInspector,IEndpointBehavior
{
// Some constants
private static string D365AuthEndpoint = "https://login.microsoftonline.com/*****/oauth2/token";
// Configuration Properties
private string client_id_;
private string client_secret_;
private string grant_type_;
private string resource_;
private int sessionTimeout_;
// Private Properties
private D365OAuthToken token_;
private DateTime tokenExpiryTime_;
public D365RESTSecurityBehavior(
string client_id,string client_secret,string grant_type,string resource,int sessiontimeout)
{
this.client_id_ = client_id;
this.client_secret_ = client_secret;
this.grant_type_ = grant_type;
this.resource_ = resource;
this.sessionTimeout_ = sessiontimeout;
}
private void FetchOAuthToken()
{
if ((tokenExpiryTime_ == null) || (tokenExpiryTime_.Compareto(DateTime.Now) <= 0))
{
StringBuilder body = new StringBuilder();
body.Append("grant_type=password&")
.Append("client_id=" + client_id_ + "&")
.Append("client_secret=" + client_secret_);
string result;
try
{
result = HttpPost(D365AuthEndpoint,body.ToString());
}
catch (WebException)
{
// do something
return;
}
// Convert the JSON response into a token object
JavaScriptSerializer ser = new JavaScriptSerializer();
this.token_ = ser.Deserialize<D365OAuthToken>(result);
this.tokenExpiryTime_ = DateTime.Now.AddSeconds(this.sessionTimeout_);
}
}
public string HttpPost(string URI,string Parameters)
{
WebRequest req = WebRequest.Create(URI);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
// Add parameters to post
byte[] data = Encoding.ASCII.GetBytes(Parameters);
req.ContentLength = data.Length;
System.IO.Stream os = req.GetRequestStream();
os.Write(data,data.Length);
os.Close();
// Do the post and get the response.
System.Net.WebResponse resp = null;
resp = req.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();
}
#region IClientMessageInspector
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,object correlationState)
{
// do nothing
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,System.ServiceModel.IClientChannel channel)
{
HttpRequestMessageProperty httpRequest = null;
if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
{
httpRequest = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
}
if (httpRequest == null)
{
// NOTE: Ideally,we shouldn’t get here for WebHttp
httpRequest = new HttpRequestMessageproperty()
{
Method = "GET",SuppressEntityBody = true
};
request.Properties.Add(HttpRequestMessageProperty.Name,httpRequest);
}
WebHeaderCollection headers = httpRequest.Headers;
FetchOAuthToken();
headers.Add(HttpRequestHeader.Authorization,"OAuth " + this.token_.access_token);
headers.Add(HttpRequestHeader.Accept,"application/xml");
return null;
}
#endregion IClientMessageInspector
#region IEndpointBehavior
public void AddBindingParameters(ServiceEndpoint endpoint,System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
// do nothing
}
public void ApplyClientBehavior(ServiceEndpoint endpoint,ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplydispatchBehavior(ServiceEndpoint endpoint,Endpointdispatcher endpointdispatcher)
{
// do nothing
}
public void Validate(ServiceEndpoint endpoint)
{
// do nothing
}
#endregion IEndpointBehavior
}
}
- class D365RESTBehaviorElement
namespace D365.BizTalk.Adapter.Behaviors
{
public class D365RESTBehaviorElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(D365RESTSecurityBehavior); }
}
protected override object CreateBehavior()
{
return new D365RESTSecurityBehavior(ClientID,ClientSecret,GrantType,Resource,Sessiontimeout);
}
[ConfigurationProperty("client_id",Isrequired = true)]
public string ClientID
{
get { return (string)this["client_id"]; }
set { this["client_id"] = value; }
}
[ConfigurationProperty("client_secret",Isrequired = true)]
public string ClientSecret
{
get { return (string)this["client_secret"]; }
set { this["client_secret"] = value; }
}
[ConfigurationProperty("grant_type",Isrequired = true)]
public string GrantType
{
get { return (string)this["grant_type"]; }
set { this["grant_type"] = value; }
}
[ConfigurationProperty("resource",Isrequired = true)]
public string Resource
{
get { return (string)this["resource"]; }
set { this["resource"] = value; }
}
[ConfigurationProperty("sessiontimeout",Isrequired = false,DefaultValue = 300)]
public int Sessiontimeout
{
get { return (int)this["sessiontimeout"]; }
set { this["sessiontimeout"] = value; }
}
}
}
Configured WCF-WebHttp custom behavior
可能是我遗漏了某些东西或做错了。任何帮助或指导将不胜感激。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)