我正在尝试为SagePay通知创建一个模型。我知道MVC模型绑定器将根据POST名称自动绑定我的所有属性。
SagePay系统传递以下表单名称:
Status
VendorTxCode
VPSTxId
VPSSignature
StatusDetail
AVSCV2
AddressResult
PostCodeResult
CV2Result
GiftAid
3DSecureStatus
CAVV
AddressStatus
PayerStatus
CardType
Last4Digits
DeclineCode
ExpiryDate
FraudResponse
BankAuthCode
我创建了以下类。
public class NotificationModel
{
public string Status { get; set; }
public string VendorTxCode { get; set; }
public string VPSTxId { get; set; }
public string VPSSignature { get; set; }
public string StatusDetail { get; set; }
public string AVSCV2 { get; set; }
public string AddressResult { get; set; }
public string PostCodeResult { get; set; }
public string CV2Result { get; set; }
public string GiftAid { get; set; }
// When binding the model will MVC ignore the underscore?
public string _3DSecureStatus { get; set; }
public string CAVV { get; set; }
public string AddressStatus { get; set; }
public string PayerStatus { get; set; }
public string CardType { get; set; }
public string Last4Digits { get; set; }
public string DeclineCode { get; set; }
public string ExpiryDate { get; set; }
public string FraudResponse { get; set; }
public string BankAuthCode { get; set; }
}
不幸的是,c#属性名称不能以数字开头。如何让模型绑定器自动将3DSecureStatus帖子名称绑定到属性?
答案 0 :(得分:2)
您可以使用自定义模型绑定器执行此操作:
public class NotificationModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
var model = this.CreateModel(controllerContext,
bindingContext, bindingContext.ModelType);
bindingContext.ModelMetadata.Model = model;
var formValue = bindingContext.ValueProvider
.GetValue(this.FormField).AttemptedValue;
var target = model.GetType().GetProperty(this.FieldToBindTo);
target.SetValue(model, formValue);
// Let the default model binder take care of the rest
return base.BindModel(controllerContext, bindingContext);
}
private readonly string FieldToBindTo = "_3DSecureStatus";
private readonly string FormField = "3DSecureStatus";
}
我没有添加错误处理,因为这个场景只处理1个字符串是微不足道的。除了字符串的实际值不是你期望的东西之外,唯一的另一个错误(在这种情况下是例外情况)你可以获得的是如果你的模型上找不到目标属性,但显然这是一个也很简单。
编辑:实际上,如果在表单上找不到该字段,您也可以获得formValue
的例外,但是再次,因为这是第三方支付系统,我倾向于说那不会不会改变。
你会这样使用它:
[HttpPost]
public ActionResult Index([ModelBinder(typeof(NotificationModelBinder))]NotificationModel model)
{
// do stuff
}
答案 1 :(得分:0)
如果您希望使用Web API控制器执行此操作,以下模型绑定器将有所帮助(实现System.Web.Http.ModelBinding.IModelBinder
:
public class SagePayTransactionNotificationModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
var model = actionContext.Request.Content.ReadAsStringAsync()
.ContinueWith(t =>
{
var formCollection = HttpUtility.ParseQueryString(t.Result);
return new SagePayTransactionNotification
{
VPSProtocol = formCollection["VPSProtocol"],
TxType = formCollection["TxType"],
VendorTxCode = formCollection["VendorTxCode"],
VPSTxId = formCollection["VPSTxId"],
Status = formCollection["Status"],
StatusDetail = formCollection["StatusDetail"],
TxAuthNo = formCollection["TxAuthNo"],
AVSCV2 = formCollection["AVSCV2"],
AddressResult = formCollection["AddressResult"],
PostcodeResult = formCollection["PostcodeResult"],
CV2Result = formCollection["CV2Result"],
GiftAid = formCollection["GiftAid"],
ThreeDSecureStatus = formCollection["3DSecureStatus"],
CAVV = formCollection["CAVV"],
CardType = formCollection["CardType"],
Last4Digits = formCollection["Last4Digits"],
VPSSignature = formCollection["VPSSignature"]
};
})
.Result;
bindingContext.Model = model;
return true;
}
}
可以像这样应用于您的Controller方法:
[ActionName("Notifications")]
public string Post([ModelBinder(typeof(SagePayTransactionNotificationModelBinder))] SagePayTransactionNotification notification)
{
...
}
我知道这并不是问题中严格要求的问题,但当我遇到与OP完全相同的问题并且认为它可能对后来的其他人有用时,这就是我最终的结果。