سؤال

The goal is to create a ActionFilter to save all your contacts automatically.

Code:

ViewModels

Origem is used to identify the view source of contact was saved (in this case only two views contato ContatoViewModel and Careers TrabalheConoscoViewModel)

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 };
    }
}

Filter

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

    }
}

Action

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);
}

Error

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: 

Error

Question

I believe it is because the _paramValue is a object. How implicit convert from an object?

Thanks.

هل كانت مفيدة؟

المحلول

The exception is certainly caused because the type you're calling the conversion on is object.

You also can't create implicit conversions from the base object type. You'll need to cast to the correct type before you're able to use your implicit converter.

I'm not a big fan of using implicit/explicit conversion operators. I much prefer a propper mapping solution like AutoMapper.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top