내 추상 기본 컨트롤러의 사용자 (user.identity.name)와 같이 사용자가 왜 있습니까?

StackOverflow https://stackoverflow.com/questions/430704

문제

나는 관련 질문을했지만 제목을 엉망으로 만들었고 아무도 그것을 이해하지 못했습니다. 나는 지금 더 정확하게 질문을 할 수 있기 때문에, 나는 새로운 질문으로 그것을 재구성하고 오래된 질문을 닫기로 결정했습니다. 그 죄송합니다.

그래서 내가하고 싶은 것은 데이터 (DB에 저장된 내 맞춤형 사용자의 별명)를 loginusercontrol에 전달하는 것입니다. 이 로그인은 html.renderpartial ()을 통해 마스터 페이지에서 렌더링되므로 실제로해야 할 일은 ViewData [ "usernickName"]가 모든 호출에 존재하는지 확인하는 것입니다. 하지만 모든 컨트롤러의 모든 작업에서 ViewData [ "usernickName"]를 채우고 싶지 않으므로 사용하기로 결정했습니다. 이 접근법 그리고 그렇게하는 것과 같은 추상 기본 컨트롤러를 만듭니다.

public abstract class ApplicationController : Controller
    {
        private IUserRepository _repUser;

        public ApplicationController()
        {
            _repUser = RepositoryFactory.getUserRepository();
            var loggedInUser = _repUser.FindById(User.Identity.Name); //Problem!
            ViewData["LoggedInUser"] = loggedInUser;
        }
    }

이런 식으로 내 파생 컨트롤러가 무엇을 하든지 사용자 정보는 이미 존재합니다.

여태까지는 그런대로 잘됐다. 이제 문제를 위해 :

user.identity.name keak에 전화 할 수 없습니다 User 이미 null입니다. 모든 파생 컨트롤러에서는 그렇지 않으므로 추상 기본 컨트롤러에만 해당됩니다.

코드의 다른 장소에서 formsauthentication을 통해 user.identity.name을 설정하고 있지만 이것이 문제가 될 수 없다고 생각합니다 - Afaik user.identity.name은 null이지만 사용자 자체는 아닙니다.

HTTPContext를 사용할 수없는 것처럼 보입니다 (또한 NULL ;-)가 여기에서 간단하지만 중요한 지점을 놓치고 있습니다. 누구든지 힌트를 줄 수 있습니까? 정말 감사하겠습니다.

도움이 되었습니까?

해결책

제 생각에는 컨트롤러의 기본 생성자가 사용자를 채우지 않고 컨트롤러 텍스트가 컨트롤러에 대해 설정된 경우에만 알려져있을 것입니다. MVC 응용 프로그램의 수명주기에 대한 문서에서 이것을 확인해야합니다 ( 여기 미리보기 버전이기 때문에 약간 오래된 것이지만 MVC의 소스 코드를 확인하십시오.

MVC가있는 코드 (미리보기 버전이지만 괜찮을 것입니다) : (컨트롤러에서)

 public IPrincipal User {
            get {
                return HttpContext == null ? null : HttpContext.User;
            }
        }

...

public HttpContextBase HttpContext {
        get {
            return ControllerContext == null ? null : ControllerContext.HttpContext;
        }
    }

코드에서 기본 생성자의 구현이 표시되지 않습니다. 그것은 ControlLerContext가 건설 시점에 null임을 증명할 것입니다.

따라서 코드를 다른 곳에서 실행해야합니다.

다른 팁

이 문제에 대한 답은 실제로 매우 간단합니다. Raimond가 지적한 이유로 생성자 내에서 코드를 실행할 수는 없지만 생성자 외부에서 수행 할 수 있습니다.

그래서 내가 한 일은 기본 컨트롤러 클래스에서 onactionExecuting ()을 우선적으로 재정의하는 것이 었습니다 (나는 그것에 대해 사용자 정의 속성을 만들었지 만 메소드를 우선적으로 작동해야 함).

이제 예상대로 작동하며 반복 코드가 없습니다.

컨트롤러가 인스턴스화 된 후까지 사용자 속성은 할당되지 않지만 다음과 함께 생성자로부터 조기 액세스를 얻을 수 있습니다.

System.Web.HttpContext.Current.User

다음과 같은 것을 사용하여 이것을 잡을 수 있습니까?

HttpContext currentContext = HttpContext.Current;
string userName = currentContext.User.Identity.Name;

아니면 httpcontext는 항상 비어 있습니까?

추상 클래스의 생성자를 통해 httpcontext를 설정할 수 있습니까? 이런 식으로 사용 하시겠습니까?

감사합니다 Raimond. 나는 명백한 것을보기에는 너무 피곤했다. @Keeney : 예, 컨텍스트는 항상 널입니다. Raimond는 이유를 지적했습니다. 어쨌든 고마워요

현재의 작업 솔루션 (내가 원했던 것은 아니지만)은 모든 컨트롤러 동작을 장식하는 데 사용하는 속성입니다. 구현은 다음과 같습니다.

public class MasterPageDataAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
            IUserRepository _repUser = RepositoryFactory.getUserRepository();
            IPrincipal siteUser = filterContext.Controller.ControllerContext.HttpContext.User;
            User loggedInUser = null;

            if (siteUser == null || siteUser.Identity.Name == null)
            {
                //do nothing
            }
            else
            {
                loggedInUser = _repUser.findUserById(siteUser.Identity.Name);
            }
            filterContext.Controller.ViewData["LoggedInUser"] = loggedInUser ?? new User { Nickname = "Guest" };
        }
    }

나는 건조 원칙을 따르는 방식으로 해당 코드를 실행하는 방법을 조사 할 것입니다. 이는 속성을 사용하여 자신을 반복하는 것을 의미하기 때문입니다. 어쩌면 일종의 인터셉터 (흥미로운 아이디어) 또는 후크가 도움이 될 수 있습니다.

그것에 대한 건배.

베이스 컨트롤러 구현 에서이 작업을 수행하고 있으며 예상대로 작동합니다.

public abstract class BaseController : Controller
{
    public bool LoggedOn
    {
        get { return User.Identity.IsAuthenticated; }
    }
}

이것은 항상 나에게 진실 또는 거짓을 반환합니다 User != null

Masterfu에게 : 나는 당신의 도움과 유사한 일을했는데, 후자의 방문자를 도울 수 있기를 바랍니다. 제 경우에는 다른 사용자를위한 컨트롤러의 저장소를 만들어야하지만 컨트롤러의 생성자 (Principal) 사용자는 준비되지 않았습니다. 그래서 컨트롤러에 대한 속성을 만들었습니다.

[CreateRepositoryByUser]
public class MFCController : Controller
{
    protected MFCRepository _repository
    {
        get { return ViewData["repository"] as MFCRepository; }
    }
...

_repository는 실제로 컨트롤러의 개인 변수가 아니라 속성에 의해 생성된다.

public class CreateRepositoryByUser : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        CreateRepository(filterContext);
    }

    public static void CreateRepository(ActionExecutingContext filterContext)
    {
        if (filterContext.Controller.ViewData["repository"] == null)
        {
            filterContext.Controller.ViewData["repository"] =
                MFCRepository.CreateMFCRepository(filterContext.Controller.ControllerContext.HttpContext.User);
        }
    }
}

다른 속성의 경우이 속성이 트리거되기 전에 (원금) 사용자를 사용하기를 원하는 경우 저장소를 별도로 작성하는 코드를 넣습니다.

MVC 파이프 라인에서 생성자로부터 호출이 너무 빨리 있습니다.

코드를 승인으로 이동하면 매개 변수에서 승인 된 사용자를 얻습니다. 나를 위해 일했습니다!

당신의 예에서 나는 다음과 같은 일을 할 것입니다.

public abstract class ApplicationController : Controller {
    private IUserRepository _repUser;

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        _repUser = RepositoryFactory.getUserRepository();
        var loggedInUser = _repUser.FindById(filterContext.HttpContext.User.Identity.Name); //Problem!
        ViewData["LoggedInUser"] = loggedInUser;
    }


}

주사 IPrincipal 필요한 경우 User 생성자에서.

 // startup.cs
 // Inject IPrincipal
 services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);

그런 다음 AS를 추가하십시오 IPrincipal 당신의 생성자에. 보장됩니다 ClaimsPrincipal Aspnet과 함께 - 그것이 무엇이기 때문입니다 HttpContext.User 이다.

비슷한 질문

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top