【问题标题】:Explicit convert from object in ActionFilter从 ActionFilter 中的对象显式转换
【发布时间】:2013-04-02 15:04:57
【问题描述】:

目标是创建一个 ActionFilter 来自动保存所有联系人。

代码:

视图模型

Origem用于标识被保存的联系人的视图来源(本例中只有两个视图contatoContatoViewModel和CareersTrabalheConoscoViewModel

public class ContatoViewModel
{
    public string Nome { get; set; }
    public string Email { get; set; }
    public string Assunto { get; set; }
    public string Mensagem { get; set; }

    public static explicit operator Contato(ContatoViewModel vm)
    {
        return new Contato { Nome = vm.Nome, Email = vm.Email, PrimeiroContato = DateTime.Now, Origem = OrigemContato.Contato };
    }
}

public class TrabalheConoscoViewModel
{
    public string Nome { get; set; }
    public string Email { get; set; }
    public string Mensagem { get; set; }
    public HttpPostedFileBase Arquivo { get; set; }

    public static explicit operator Contato(TrabalheConoscoViewModel vm)
    {
        return new Contato{ Nome = vm.Nome, Email = vm.Email, PrimeiroContato=DateTime.Now, Origem = OrigemContato.Candidato };
    }
}

过滤器

public class LogContatoAttribute : ActionFilterAttribute
{
    private readonly string _paramName;
    private object _paramValue = null;
    public LogContatoAttribute(string paramName = "vm")
    {
        _paramName = paramName;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.ActionParameters.ContainsKey(_paramName))
            _paramValue = filterContext.ActionParameters[_paramName];
        else
            throw new ArgumentException("Parâmetro não encontrado.", _paramName);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var a = (Contato)_paramValue; //Error!!!!

        // Save in database

    }
}

动作

public ActionResult contato()
{
    return View(new ContatoViewModel());
}

[HttpPost]
[ValidateAntiForgeryToken]
[LogContato("vm")]
public ActionResult contato(ContatoViewModel vm)
{
    if (ModelState.IsValid)
    {
        new mailController().contato(vm).Deliver();
        return RedirectToRoute("Default", new RouteValueDictionary { { "controller", "home" }, { "action", "contato" } });
    }

    ModelState.AddModelError("", "Não foi possível enviar sua mensagem.");
    return View(vm);
}

错误

System.InvalidCastException was unhandled by user code
  HResult=-2147467262
  Message=Unable to cast object of type 'CreditoImobiliarioBB.WebSite.ViewModels.ContatoViewModel' to type 'CreditoImobiliarioBB.WebSite.Models.Contato'.
  Source=CreditoImobiliarioBB.WebSite
  StackTrace:
       at CreditoImobiliarioBB.WebSite.Infra.Filters.LogContatoAttribute.OnActionExecuted(ActionExecutedContext filterContext) in w:\Clients\creditoimobiliariobb\website\src\CreditoImobiliarioBB.WebSite\Infra\Filters\LogContato.cs:line 27
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
       at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
  InnerException: 

问题

我相信这是因为_paramValue 是一个对象。 如何从对象隐式转换?

谢谢。

【问题讨论】:

    标签: c# c#-4.0 asp.net-mvc-4 implicit-conversion action-filter


    【解决方案1】:

    这个异常肯定是因为你调用转换的类型是object

    您也不能从基本 object 类型创建隐式转换。您需要先转换为正确的类型,然后才能使用隐式转换器。

    我不太喜欢使用隐式/显式转换运算符。我更喜欢像 AutoMapper 这样的 propper 映射解决方案。

    【讨论】:

    • 我用的是AutoMapper,但是这个问题很准时。我认为这不能证明 AutoMapper 的合理性(至少目前如此)。在没有 AutoMapper 的情况下还有其他方法可以解决这个问题吗?
    • 如果你想继续使用你的转换运算符,那么你只需要转换为正确的类型。您可以将其暗示为简单的if (_paramValue is ContatoViewModel){ // cast it here and convert }
    猜你喜欢
    • 1970-01-01
    • 2013-10-26
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    相关资源
    最近更新 更多