对此的答案可能非常明显。但需要一些帮助...
我目前正在使用UPS API /服务来生成测试标签。一切都很好。但为了获得认证,我必须向UPS发送来自请求和原始XML的原始XML。响应。
我不是发送原始xml,而是使用服务及其各种属性。是否在发货结果中的某处返回了原始XML?或者必须手动序列化请求&回应只是为了满足UPS在审核中的要求?
这是我的代码(一切正常,我能够生成一个标签。但是我如何得到请求和响应xml?)
try
{
ShipService shpSvc = new ShipService();
ShipmentRequest shipmentRequest = new ShipmentRequest();
UPSSecurity upss = new UPSSecurity();
UPSSecurityServiceAccessToken upssSvcAccessToken = new UPSSecurityServiceAccessToken();
upssSvcAccessToken.AccessLicenseNumber = s.APIKey;
upss.ServiceAccessToken = upssSvcAccessToken;
UPSSecurityUsernameToken upssUsrNameToken = new UPSSecurityUsernameToken();
upssUsrNameToken.Username = s.Username;
upssUsrNameToken.Password = s.Password;
upss.UsernameToken = upssUsrNameToken;
shpSvc.UPSSecurityValue = upss;
RequestType request = new RequestType();
String[] requestOption = { "nonvalidate" };
request.RequestOption = requestOption;
shipmentRequest.Request = request;
ShipmentType shipment = new ShipmentType();
ShipperType shipper = new ShipperType();
shipper.ShipperNumber = s.ShipperAccountNumber;
PaymentInfoType paymentInfo = new PaymentInfoType();
ShipmentChargeType shpmentCharge = new ShipmentChargeType();
BillShipperType billShipper = new BillShipperType();
billShipper.AccountNumber = s.ShipperAccountNumber;
shpmentCharge.BillShipper = billShipper;
shpmentCharge.Type = "01";
ShipmentChargeType[] shpmentChargeArray = { shpmentCharge };
paymentInfo.ShipmentCharge = shpmentChargeArray;
shipment.PaymentInformation = paymentInfo;
ShipWebReference.ShipAddressType shipperAddress = new ShipWebReference.ShipAddressType();
String[] addressLine = { s.ShipperAddressLine };
shipperAddress.AddressLine = addressLine;
shipperAddress.City = s.ShipperCity;
shipperAddress.PostalCode = s.ShipperZip;
shipperAddress.StateProvinceCode = s.ShipperState;
shipperAddress.CountryCode = "US";
shipperAddress.AddressLine = addressLine;
shipper.Address = shipperAddress;
shipper.Name = s.ShipperName;
shipper.AttentionName = s.ShipperName;
ShipPhoneType shipperPhone = new ShipPhoneType();
shipperPhone.Number = s.ShipperPhone;
shipper.Phone = shipperPhone;
shipment.Shipper = shipper;
ShipFromType shipFrom = new ShipFromType();
ShipWebReference.ShipAddressType shipFromAddress = new ShipWebReference.ShipAddressType();
String[] shipFromAddressLine = { s.ShipperAddressLine };
shipFromAddress.AddressLine = addressLine;
shipFromAddress.City = s.ShipperCity;
shipFromAddress.PostalCode = s.ShipperZip;
shipFromAddress.StateProvinceCode = s.ShipperState;
shipFromAddress.CountryCode = "US";
shipFrom.Address = shipFromAddress;
shipFrom.AttentionName = s.ShipperName;
shipFrom.Name = s.ShipperName;
shipment.ShipFrom = shipFrom;
ShipToType shipTo = new ShipToType();
ShipToAddressType shipToAddress = new ShipToAddressType();
String[] addressLine1 = { s.ShipToAddressLine };
shipToAddress.AddressLine = addressLine1;
shipToAddress.City = s.ShipToCity;
shipToAddress.PostalCode = s.ShipToZip;
shipToAddress.StateProvinceCode = s.ShipToState;
shipToAddress.CountryCode = "US";
shipTo.Address = shipToAddress;
shipTo.AttentionName = s.ShipToName;
shipTo.Name = s.ShipToName;
ShipPhoneType shipToPhone = new ShipPhoneType();
shipToPhone.Number = s.ShipToPhone;
shipTo.Phone = shipToPhone;
shipment.ShipTo = shipTo;
ServiceType service = new ServiceType();
service.Code = "03";
shipment.Service = service;
PackageType package = new PackageType();
PackageWeightType packageWeight = new PackageWeightType();
packageWeight.Weight = s.PackageWeight;
ShipUnitOfMeasurementType uom = new ShipUnitOfMeasurementType();
uom.Code = "LBS";
packageWeight.UnitOfMeasurement = uom;
package.PackageWeight = packageWeight;
PackagingType packType = new PackagingType();
packType.Code = "02";
package.Packaging = packType;
PackageType[] pkgArray = { package };
shipment.Package = pkgArray;
LabelSpecificationType labelSpec = new LabelSpecificationType();
LabelStockSizeType labelStockSize = new LabelStockSizeType();
labelStockSize.Height = "6";
labelStockSize.Width = "4";
labelSpec.LabelStockSize = labelStockSize;
LabelImageFormatType labelImageFormat = new LabelImageFormatType();
LabelDeliveryType labelDel = new LabelDeliveryType();
labelDel.LabelLinksIndicator = "";
labelImageFormat.Code = "GIF";
PackageServiceOptionsType packServiceOptions = new PackageServiceOptionsType();
PackageDeclaredValueType decType = new PackageDeclaredValueType();
decType.CurrencyCode = "USD";
decType.MonetaryValue = s.PackageValue;
packServiceOptions.DeclaredValue = decType;
package.PackageServiceOptions = packServiceOptions;
labelSpec.LabelImageFormat = labelImageFormat;
ShipmentTypeShipmentServiceOptions shipServOpt = new ShipmentTypeShipmentServiceOptions();
shipment.ShipmentServiceOptions = shipServOpt;
shipmentRequest.LabelSpecification = labelSpec;
shipmentRequest.Shipment = shipment;
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
Console.WriteLine(shipmentRequest);
shipmentResponse = shpSvc.ProcessShipment(shipmentRequest);
}
答案 0 :(得分:1)
我遇到了同样的问题,幸运的是,我解决了问题;)
您需要注册SOAP扩展:
[ReflectionPermission(SecurityAction.Demand, Unrestricted = true)]
public static void RegisterSoapExtension(Type type, int priority, PriorityGroup group)
{
if (!type.IsSubclassOf(typeof(SoapExtension)))
{
throw new ArgumentException("Type must be derived from SoapException.", "type");
}
if (priority < 1)
{
throw new ArgumentOutOfRangeException("priority", priority, "Priority must be greater or equal to 1.");
}
// get the current web services settings...
WebServicesSection wss = WebServicesSection.Current;
// set SoapExtensionTypes collection to read/write...
FieldInfo readOnlyField = typeof(System.Configuration.ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
readOnlyField.SetValue(wss.SoapExtensionTypes, false);
// inject SoapExtension...
//wss.SoapExtensionTypes.Add(new SoapExtensionTypeElement(type, priority, group));
System.Web.Services.Configuration.SoapExtensionTypeElement soapInterceptor = new SoapExtensionTypeElement();
soapInterceptor.Type = type;
soapInterceptor.Priority = priority;
soapInterceptor.Group = group;
wss.SoapExtensionTypes.Add(soapInterceptor);
// set SoapExtensionTypes collection back to readonly and clear modified flags...
MethodInfo resetModifiedMethod = typeof(System.Configuration.ConfigurationElement).GetMethod("ResetModified", BindingFlags.NonPublic | BindingFlags.Instance);
resetModifiedMethod.Invoke(wss.SoapExtensionTypes, null);
MethodInfo setReadOnlyMethod = typeof(System.Configuration.ConfigurationElement).GetMethod("SetReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
setReadOnlyMethod.Invoke(wss.SoapExtensionTypes, null);
}
您需要定义实际的扩展名:
/// <summary>
/// SOAP Extension that traces the SOAP request and
/// SOAP response to a SOAP API Web service.
/// </summary>
public class TraceExtension : SoapExtension
{
private Stream oldStream;
private Stream newStream;
private static XmlDocument xmlRequest;
/// <summary>
/// Gets the outgoing XML request
/// </summary>
public static XmlDocument XmlRequest
{
get { return xmlRequest; }
}
private static XmlDocument xmlResponse;
/// <summary>
/// Gets the incoming XML response
/// </summary>
public static XmlDocument XmlResponse
{
get { return xmlResponse; }
}
/// <summary>
/// Save the Stream representing the SOAP request
/// or SOAP response into a local memory buffer.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public override Stream ChainStream(Stream stream)
{
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
/// <summary>
/// If the SoapMessageStage is such that the SoapRequest or
/// SoapResponse is still in the SOAP format to be sent or received,
/// save it to the xmlRequest or xmlResponse property.
/// </summary>
/// <param name="message"></param>
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
xmlRequest = GetSoapEnvelope(newStream);
CopyStream(newStream, oldStream);
break;
case SoapMessageStage.BeforeDeserialize:
CopyStream(oldStream, newStream);
xmlResponse = GetSoapEnvelope(newStream);
break;
case SoapMessageStage.AfterDeserialize:
break;
}
}
/// <summary>
/// Returns the XML representation of the Soap Envelope in the supplied stream.
/// Resets the position of stream to zero.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
private XmlDocument GetSoapEnvelope(Stream stream)
{
var xml = new XmlDocument();
stream.Position = 0;
var reader = new StreamReader(stream);
xml.LoadXml(reader.ReadToEnd());
stream.Position = 0;
return xml;
}
/// <summary>
/// Copies a stream.
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
private void CopyStream(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
/// <summary>
/// Included only because it must be implemented.
/// </summary>
/// <param name="methodInfo"></param>
/// <param name="attribute"></param>
/// <returns></returns>
public override object GetInitializer(LogicalMethodInfo methodInfo,
SoapExtensionAttribute attribute)
{
return null;
}
/// <summary>
/// Included only because it must be implemented.
/// </summary>
/// <param name="WebServiceType"></param>
/// <returns></returns>
public override object GetInitializer(Type WebServiceType)
{
return null;
}
/// <summary>
/// Included only because it must be implemented.
/// </summary>
/// <param name="initializer"></param>
public override void Initialize(object initializer)
{
}
}
然后你需要注册扩展名:
RegisterSoapExtension(typeof(TraceExtension), 1, 0);
最后,在您的请求/响应完成后,您需要保存XML:
TraceExtension.XmlRequest.Save(@"c:\temp\ForwardRequest.xml");
TraceExtension.XmlResponse.Save(@"c:\temp\ForwardResponse{0}.xml");
警告:这实际上就是我过去通过UPS认证的内容,但这段代码只使用过一次。因此,除了单一的东西之外,它可能不是最好的质量,漂亮或非常有用。
答案 1 :(得分:0)
对于那些像我一样挣扎的人,如果你对Request和Respose都获得Null,则需要在实例化ShipService之前注册扩展名。
TraceExtension.RegisterSoapExtension(typeof(TraceExtension),1,0); ShipService shpSvc = new ShipService();
希望这有助于某人:)