2013-02-13 1 views
2

MVC 컨트롤러에서 페이지 수명주기를 가로 채서 페이지 또는 DOM 어딘가에 코드를 삽입 할 수 있습니까? 페이지 머리글과 바닥 글에 HTML, CSS 및 JavaScript를 추가하고 싶지만 어딘가에 어셈블리에 포함 된 _Layout보기에 추가하지 마십시오. 그래서 Global.asax/Application_Start의 컨트롤러에서이 작업을 수행하고 싶습니다. 이것이 가능한가?HTML 또는 스크립트를 MVC 페이지 수명주기에 삽입 하시겠습니까?

답변

1

나는 비슷한 것을했습니다.

첫째, 당신은

두 번째를 (당신이 코드를 삽입 할) 레이아웃 파일 내부에 자리를 추가해야합니다, 당신은 당신의 Global.asax에 글로벌 ActionFilterAttribute를 추가해야합니다. FilterAttribute에서 OnActionExecuted 만 필터링하고 ViewResults 만 필터링하십시오.

셋째, html 코드 내의 자리 표시자를 검색 할 새 필터를 사용하여 Response.Filter를 변경하고 자신의 필터로 바꾸어야합니다.

정확하게 썼습니다. 코드의 어느 곳에서나 스타일 & 스크립트를 선언하는 방법을 추가했습니다. 결과가 완료되면 리소스가 head 태그에 삽입됩니다.

public class DynamicHeaderHandler : ActionFilterAttribute 
{ 
    private static readonly byte[] _headClosingTagBuffer = Encoding.UTF8.GetBytes("</head>"); 
    private static readonly byte[] _placeholderBuffer = Encoding.UTF8.GetBytes(DynamicHeader.SectionPlaceholder); 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     if (filterContext.Result is ViewResult) 
     { 
      filterContext.HttpContext.Response.Filter = new ResponseFilter(filterContext.HttpContext.Response.Filter); 
     } 

     base.OnActionExecuted(filterContext); 
    } 

    private class ResponseFilter : MemoryStream 
    { 
     private readonly Stream _outputStream; 

     public ResponseFilter(Stream aOutputStream) 
     { 
      _outputStream = aOutputStream; 
     } 

     public override void Close() 
     { 
      _outputStream.Flush(); 
      _outputStream.Close(); 
     } 

     public override void Write(byte[] buffer, int offset, int count) 
     { 
      var maxIndex = IndexOfSubArray(buffer, _headClosingTagBuffer); 
      var index = IndexOfSubArray(buffer, _placeholderBuffer, maxIndex); 

      if (index == -1) 
      { 
       _outputStream.Write(buffer, offset, count); 
      } 
      else 
      { 
       var html = DynamicHeader.GetHtml(); 
       var injectBytes = Encoding.UTF8.GetBytes(html); 
       var newBuffer = buffer.Take(index).Concat(injectBytes).Concat(buffer.Skip(index + _placeholderBuffer.Length)).ToArray(); 
       _outputStream.Write(newBuffer, 0, newBuffer.Length); 
      } 
     } 

     private static int IndexOfSubArray(byte[] aBuffer, byte[] aSubBuffer, int aMaxIndex = int.MaxValue) 
     { 
      if (aBuffer.Length < aSubBuffer.Length) 
      { 
       return -1; 
      } 

      for (var outerIndex = 0; outerIndex < aBuffer.Length && outerIndex < aMaxIndex; ++outerIndex) 
      { 
       var isEqual = true; 
       for (int subInnerIndex = 0, innerIndex = outerIndex; subInnerIndex < aSubBuffer.Length && innerIndex < aBuffer.Length; ++subInnerIndex, ++innerIndex) 
       { 
        if (aBuffer[innerIndex] != aSubBuffer[subInnerIndex]) 
        { 
         isEqual = false; 
         break; 
        } 
       } 

       if (isEqual) 
       { 
        return outerIndex; 
       } 
      } 

      return -1; 
     } 
    } 
} 

나는 당신과 관련된 아마 ActionFilterAttribute를 첨부했습니다. 당신은 전체 코드를 보려면

, 당신은 여기 방문 할 수 있습니다 : 쓰기 여러 번 호출, 첫 쓰기까지가 어떤 경우 Add Styles & Scripts Dynamically

+0

에' '? 이 경우 코드가 머리 끝을 감지하지 못합니다. 일반적으로 Write로 전달되는 청크는 일반적인 HTML 헤더보다 커야하지만 여전히 그렇습니다. 아마도 모든 입력을 버퍼링하고 버퍼링 된 입력을 닫는 태그 버퍼와 비교해야합니다. 머리가 끝나면 래핑 된 출력 스트림에 직접 모든 것을 쓸 수 있습니다. –

+0

그 사건을 생각하지 않았습니까! 어쨌든 나는 결코 문제가 없었기 때문에 나는 운이 좋았고이 경우에 빠지지 않았다. 나는 그것을 내 편에서 고칠 것이다. 하지만 도움이 되었습니까? –