‘object’ does not contain a definition for ‘Action’ when using IdentityUser with OAuth

‘object’ does not contain a definition for ‘Action’ when using IdentityUser with OAuth

I am not sure how or why this is occurring but after spending a day on google and stackoverflow I need some help as to what the issue is.
This is the error...
Server Error in '/' Application.

    'object' does not contain a definition for 'Action'

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

    Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'Action'

    Source Error: 


    Line 15:     else
    Line 16:     {
    Line 17:         string action = **Model.Action**;
    Line 18:         string returnUrl = Model.ReturnUrl;
    Line 19:         using (Html.BeginForm(action, "Account", new { ReturnUrl = returnUrl }))

    Source File: c:\Users\Developer\Source\Repos\Zenwire-Master\Zenwire\Views\Account\_ExternalLoginsListPartial.cshtml    Line: 17 

~/Controllers/AccountController
    using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.Owin.Security;
using Zenwire.Models;

namespace Zenwire.Controllers
{
    [Authorize]
    public class AccountController : Controller
    {
        public AccountController()
            : this(new UserManager(new UserStore(new IdentityDbContext())))
        {
        }

        public AccountController(UserManager userManager)
        {
            UserManager = userManager;
        }

        public UserManager UserManager { get; private set; }

        //
        // GET: /Account/Login
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task Login(LoginViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                var user = await UserManager.FindAsync(model.UserName, model.Password);
                if (user != null)
                {
                    await SignInAsync(user, model.RememberMe);
                    return RedirectToLocal(returnUrl);
                }
                else
                {
                    ModelState.AddModelError("", "Invalid username or password.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // GET: /Account/Register
        [AllowAnonymous]
        public ActionResult Register()
        {
            return View();
        }

        //
        // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser()
                {
                    UserName = model.UserName,
                    FirstName = model.FirstName,
                    LastName = model.LastName,
                    Address = model.Address,
                    City = model.City,
                    PostalCode = model.PostalCode,
                    Province = model.Province,
                    Phone = model.Phone,
                    Email = model.Email
                };

                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await SignInAsync(user, isPersistent: false);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    AddErrors(result);
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // POST: /Account/Disassociate
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task Disassociate(string loginProvider, string providerKey)
        {
            ManageMessageId? message = null;
            IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
            if (result.Succeeded)
            {
                message = ManageMessageId.RemoveLoginSuccess;
            }
            else
            {
                message = ManageMessageId.Error;
            }
            return RedirectToAction("Manage", new { Message = message });
        }

        //
        // GET: /Account/Manage
        public ActionResult Manage(ManageMessageId? message)
        {
            ViewBag.StatusMessage =
                message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
                : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
                : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
                : message == ManageMessageId.Error ? "An error has occurred."
                : "";
            ViewBag.HasLocalPassword = HasPassword();
            ViewBag.ReturnUrl = Url.Action("Manage");
            return View();
        }

        //
        // POST: /Account/Manage
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task Manage(ManageUserViewModel model)
        {
            bool hasPassword = HasPassword();
            ViewBag.HasLocalPassword = hasPassword;
            ViewBag.ReturnUrl = Url.Action("Manage");
            if (hasPassword)
            {
                if (ModelState.IsValid)
                {
                    IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
                    }
                    else
                    {
                        AddErrors(result);
                    }
                }
            }
            else
            {
                // User does not have a password so remove any validation errors caused by a missing OldPassword field
                ModelState state = ModelState["OldPassword"];
                if (state != null)
                {
                    state.Errors.Clear();
                }

                if (ModelState.IsValid)
                {
                    IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
                    }
                    else
                    {
                        AddErrors(result);
                    }
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        //
        // POST: /Account/ExternalLogin
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult ExternalLogin(string provider, string returnUrl)
        {
            // Request a redirect to the external login provider
            return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
        }

        //
        // GET: /Account/ExternalLoginCallback
        [AllowAnonymous]
        public async Task ExternalLoginCallback(string returnUrl)
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }

            // Sign in the user with this external login provider if the user already has a login
            var user = await UserManager.FindAsync(loginInfo.Login);
            if (user != null)
            {
                await SignInAsync(user, isPersistent: false);
                return RedirectToLocal(returnUrl);
            }
            else
            {
                // If the user does not have an account, then prompt the user to create an account
                ViewBag.ReturnUrl = returnUrl;
                ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
            }
        }

        //
        // POST: /Account/LinkLogin
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult LinkLogin(string provider)
        {
            // Request a redirect to the external login provider to link a login for the current user
            return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
        }

        //
        // GET: /Account/LinkLoginCallback
        public async Task LinkLoginCallback()
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
            if (loginInfo == null)
            {
                return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
            }
            var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
            if (result.Succeeded)
            {
                return RedirectToAction("Manage");
            }
            return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
        }

        //
        // POST: /Account/ExternalLoginConfirmation
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
        {
            if (User.Identity.IsAuthenticated)
            {
                return RedirectToAction("Manage");
            }

            if (ModelState.IsValid)
            {
                // Get the information about the user from the external login provider
                var info = await AuthenticationManager.GetExternalLoginInfoAsync();
                if (info == null)
                {
                    return View("ExternalLoginFailure");
                }
                var user = new ApplicationUser()
                {
                    UserName = model.UserName,
                    FirstName = model.FirstName,
                    LastName = model.LastName,
                    Address = model.Address,
                    City = model.City,
                    PostalCode = model.PostalCode,
                    Province = model.Province,
                    Phone = model.Phone,
                    Email = model.Email
                };

                var result = await UserManager.CreateAsync(user);
                if (result.Succeeded)
                {
                    result = await UserManager.AddLoginAsync(user.Id, info.Login);
                    if (result.Succeeded)
                    {
                        await SignInAsync(user, isPersistent: false);
                        return RedirectToLocal(returnUrl);
                    }
                }
                AddErrors(result);
            }

            ViewBag.ReturnUrl = returnUrl;
            return View(model);
        }

        //
        // POST: /Account/LogOff
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult LogOff()
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("Index", "Home");
        }

        //
        // GET: /Account/ExternalLoginFailure
        [AllowAnonymous]
        public ActionResult ExternalLoginFailure()
        {
            return View();
        }

        [ChildActionOnly]
        public ActionResult RemoveAccountList()
        {
            var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
            ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
            return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && UserManager != null)
            {
                UserManager.Dispose();
                UserManager = null;
            }
            base.Dispose(disposing);
        }

        #region Helpers
        // Used for XSRF protection when adding external logins
        private const string XsrfKey = "XsrfId";

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        private async Task SignInAsync(ApplicationUser user, bool isPersistent)
        {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
        }

        private void AddErrors(IdentityResult result)
        {
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError("", error);
            }
        }

        private bool HasPassword()
        {
            var user = UserManager.FindById(User.Identity.GetUserId());
            if (user != null)
            {
                return user.PasswordHash != null;
            }
            return false;
        }

        public enum ManageMessageId
        {
            ChangePasswordSuccess,
            SetPasswordSuccess,
            RemoveLoginSuccess,
            Error
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }

        private class ChallengeResult : HttpUnauthorizedResult
        {
            public ChallengeResult(string provider, string redirectUri)
                : this(provider, redirectUri, null)
            {
            }

            public ChallengeResult(string provider, string redirectUri, string userId)
            {
                LoginProvider = provider;
                RedirectUri = redirectUri;
                UserId = userId;
            }

            public string LoginProvider { get; set; }
            public string RedirectUri { get; set; }
            public string UserId { get; set; }

            public override void ExecuteResult(ControllerContext context)
            {
                var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
                if (UserId != null)
                {
                    properties.Dictionary[XsrfKey] = UserId;
                }
                context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
            }
        }
        #endregion
    }
}

~/View
@using Microsoft.Owin.Security

Use another service to log in.


@{ var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes(); if (loginProviders.Count() == 0) {

There are no external authentication services configured. See this article for details on setting up this ASP.NET application to support logging in via external services.

} else { string action = Model.Action; string returnUrl = Model.ReturnUrl; using (Html.BeginForm(action, "Account", new { ReturnUrl = returnUrl })) { @Html.AntiForgeryToken()

@foreach (AuthenticationDescription p in loginProviders) { }

} } } ~/Models/IdentityModels using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Entity; using Microsoft.AspNet.Identity.EntityFramework; namespace Zenwire.Models { // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. public class ApplicationUser : IdentityUser { public string FirstName { get; set; } public string LastName { get; set; } public string Address { get; set; } public string City { get; set; } public string Province { get; set; } public string PostalCode { get; set; } [DataType(DataType.PhoneNumber)] public string Phone { get; set; } [DataType(DataType.EmailAddress)] public string Email { get; set; } public virtual string Fullname { get { return FirstName + " " + LastName; } } } } ~/App_Start/IdentityConfig using Zenwire.Models; using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework; using Microsoft.AspNet.Identity.Owin; using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Web; using Zenwire.Repositories; namespace Zenwire { public class IdentityInitializer : DropCreateDatabaseAlways { protected override void Seed(ZenwireContext context) { var userManager = new UserManager(new UserStore(context)); var roleManager = new RoleManager(new RoleStore(context)); const string username = "Admin"; const string password = "123456"; //Create Role roleManager.Create(new IdentityRole("Admin")); userManager.Create(new ApplicationUser() { UserName = username }); //Create Role Admin if it does not exist if (!roleManager.RoleExists("Admin")) { roleManager.Create(new IdentityRole("Admin")); } //Create User=Admin with password=123456 var user = new ApplicationUser { UserName = username }; var adminresult = userManager.Create(user, password); //Add User Admin to Role Admin if (adminresult.Succeeded) { userManager.AddToRole(user.Id, username); } base.Seed(context); } } }

Solutions/Answers:

Answer 1:

This problem seems to randomly occur in MVC 5 projects. For no reason I fathom, so far, it simply stops allowing the use of dynamic/anonymous types in partial views.

I just had the same issue, with the _ExternalLoginsListPartial.cshtml page and even rolling back added project changes made no difference. Once broken it seems to stay broken.

The only solution so far is to not use anonymous types, but instead add strongly typed classes with the required properties.

e.g. add a new class like this:

namespace Project.Models
{
    public class ExternalLoginViewModel
    {
        public string Action { get; set; }
        public string ReturnUrl { get; set; }
    }
}

and reference it in the partial view with

@model Project.Models.ExternalLoginViewModel

and where the partial view is rendered, change to:

@Html.Partial("_ExternalLoginsListPartial", new Project.Models.ExternalLoginViewModel() { Action = "ExternalLogin", ReturnUrl = ViewBag.ReturnUrl })

Answer 2:

This bug is beeing looked at at Microsoft.

Update:
https://connect.microsoft.com/VisualStudio/feedback/details/813133/bug-in-mvc-5-framework-asp-net-identity-modules

Answer 3:

I has the same issue and was able to get it back going by deleting the application’s bin/ and obj/ folders.

This will get you going, but I like @TrueBlueAussie’s idea, although I have not tried it yet.

Answer 4:

This issue appears to be fixed now according to Microsoft https://connect.microsoft.com/VisualStudio/feedback/details/813133/bug-in-mvc-5-framework-asp-net-identity-modules

Personally, I resolved the issue with a NuGet: Update-Package for all packages in my solution. I have attached the before and after of the packages.config for reference.

enter image description here

Answer 5:

this might look silly but it is what I had..

i started a web app that has the external login feature working fine with google and facebook and twitter then i decided that the login buttons should look pretty so i used the following link:
http://www.beabigrockstar.com/pretty-social-login-buttons-for-asp-net-mvc-5/

after that i run into this strange error (object does not contain definition for action) and came to this post..

first I tried TrueBlueAussie solution and didn’t work for me then I tried Antonio Chagoury..

then I put a breakpoint on the action :

public ActionResult ExternalLogin(string provider, string returnUrl)

then hovering over the provider , it shows null ?? while i click on facebook or twitter etc..

so i went back to my button on the _ExternalLoginsListPartial view and looked at the button to find that the name attribute has one extraspace :

name=" provider" value="@p.AuthenticationType"

removing that space worked for me !!

name="provider" value="@p.AuthenticationType"

I don’t know how did i get that extraspace before the word”provider”

however ..the lesson i learned is that you should be meticulous and carefull and think of simple causes before you ran into long operation of troubleshooting..

I hope this will help those people who keep pulling their hair to find that it is only a typo errors 😛

Answer 6:

This happens to me constantly when using dynamic types in partial views.

The easiest way to deal with it is to clean your solution and re-build.

Answer 7:

OK, that was really frustrating cause in my project. After I removed properties from the ExternalLoginConfirmationViewModel model I got the same error.

Turned out to be there were errors in ExternalLoginConfirmationViewModel.cshtm which didn’t stop the build progress and showed in the error list window just once and then they all those errors are gone, and appear after a while randomly.

Make sure you are not referencing nonexisting properties in the ExternalLoginConfirmationViewModel.cshtm

like that:

 <div class="form-group">
        @Html.LabelFor(m => m.HomeTown, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.HomeTown, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.HomeTown)
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.BirthDate, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.BirthDate, new { @class = "form-control" })
            @Html.ValidationMessageFor(m => m.BirthDate)
        </div>
    </div>   

Answer 8:

Your application throws an exception in the partial view called _ExternalLoginsListPartial. It throws because the partial view has been instantiated with a model that doesn’t have the expected property called Action.
This partial is included in the Login view in projects created from the default mvc project template.

It is included like this:

        @Html.Partial("_ExternalLoginsListPartial", new { Action = "ExternalLogin", ReturnUrl = ViewBag.ReturnUrl })

In your application the _ExternalLoginsListPartial partial is included somewhere without passing a model that has a Action property.
You could search all views to find all places you may have included the _ExternalLoginsListPartial and make sure that you always pass a valid model to the partial.

Our Awesome Tools

References