본문 바로가기

.NET/MVC.NET

ASP.NET MVC 3 Real Time Collaborative Apps with SignalR

좀 나온지 됐지만 ㅋㅋ 한번 꼭 읽어보세요(시간있을때 번역해 보겠습니다.^^;일때문에)

http://www.dotnetcurry.com/ShowArticle.aspx?ID=780

에서 퍼온 글입니다.

 
여기서 우리는 blog app를 MVC3와 Signal$을 이용하여 개발할것입니다. In this article, we’ll create a simple blog app using ASP.NET MVC 3 and SignalR, 이러한 기술은 여러 유저에게 공통의 기사를 리얼타임에 볼수이게 해 줍니다.

SignalR은 무엇인가?

사전적으로 – 클라이언트와 서버의 persistent 커넥션을 유지하기위한 비동기 프레임워크 입니다.

사전적이아닌 – 서버사이드의 ASP.NET와 JavaScript에 탑 레이어에 구성된 프레임워크입니다. David Fowler와 Damien Edwards가  SignalR project on GitHub에서 관리하고 있습니다.

SignalR은 웹클라이언트와 서버간의 커넥션을 계속 열어두는 원천적인 기술을 추상화 하였습니다. 뒷단에서 SignalR은 logn polling이라는 기존의 기술을 사용하였습니다. 그러나  웹소켓이 프로토콜화되면서 SignalR은 WebSocket을 뒷단에서 사용할수도 있습니다.
SignalR은 서버단에서 Task Parallel Library를 사용하고있습니다(병력프로그램).

왜 SignalR이 필요한가?

long polling이 사용되는 대부분의 샘플은 Stock Tickers나 Chat Clients것입니다. 그러나 우리가 볼 SignalR은 새로운 가능성들을 위한 도구들을 열어두었습니다. 이러한것들로 인해 Rich Collaborative Application을 개발할수 있습니다.

SignalR로 비지니스 문제들을 풀자.

이론적인것은 이것으로 충분하고 실제로 한번 들어가보죠. Google Docs를 대부분 해보셨을 것입니다. 2명 이상의 유저들이 한 Document를 공유하여 여러명이 수정할수 있게 되어있습니다. 각 사람은 다른 색으로된 표식을 갖고 그리하여 누가 수정했는지 알수 있습니다.

만약 여러분의 App에 'Review'와 같은 기능들을 심을수 있다면 얼마나 행복한 일입니까?
생략 

여기서는 간단한 blog app를 만들고 멀티 유저들이 리얼타임으로 기사를 볼수 있게 할것입니다.

Step 1: ASP.NET project를 생성합니다..

In Visual Studio From File > New Project, MVC 3 Web Application template을 선택합니다.

asp-mvc-project

‘Intranet Application’를 선택합니다. 이렇게 하면 Windows Authentiction mode가 기본으로 된 프로젝트가 생성됩니다.

우리는 Razor View engine을 사용할거고 HTML5 semantic markup 체크하여 HTML마크웝을 사용할것입니다..

razor-view

만약 Nuget Package Manager가 설치됐다면 Step 2로 넘어가세요. 아니면 Tools > Extension Manager, 그리고 ‘Online Gallery’ 에서 ‘NuGet Package Manager’을 설치하세요.
nuget-manager

설치된다음 Visual Studio를 재시작하여야합니다.

Step 2: Nuget에서 SignalR dependencies을 설치합니다.

View->Other Windows->Package Manager Console menu item으로 가서 콘솔창에  Install-package SignalR 을 타입핑합니다.

package들이 다운로드되고 설치될 때까지 기다립니다. The jQuery dependencies또한 추가될것입니다.
package-mgr-console
 

Step 3: Data Model 설정

우리는 EF에 Code First를 이요할것이고 우리의 Model를 만들겁니다. entity는 BlogPost라고 하고 거기에는 간단한 3개의 프로퍼티를 생성합니다.(Id, Title, BlogBody)
 
data-model

Note: Since the focus of the article is SignalR I am cutting some ‘pattern corners’ by putting Display attributes in my Entity Model and skipping the View model abstraction.

BlogPostContext class를 DbContext에서 상속받아 생성합니다. 솔루션을 빌드합니다.

Step 4: Scaffold로 Controllers 와 Views 생성

scafoold를 사용하여 우리는 Controller와 View를 생성합니다.

add-controller

Template을 생성하고, Model class와 Data context class를 생성합니다.

controller-dialog

Step 5: ‘Review’ Controller과View 생성

기본적으로, scaffolding는 Index를 생성해주고 Create, Edit, Delete view를 각 action 메서드에 맵핑해 줍니다. 

BlogPostController에, Review action method를 다음과 같이 추가합니다:

review-action-method

Views\BlogPost에 Review.cshtml를 추가합니다.

review-cshtml

Index.cshtml에 링크를 아래와 같이 ‘Review’ 로 합니다..

review-view-link

Step 6: SignalR을 실행하기 위해

On the Server Side
프로젝트에 SignalR이라는 폴더를 만들고 BlogHub.cs클래스를 추가합니다. 그리고 아래와 같이 코딩을 합니다.

blog-hub-class
이 클래스는 'HubName'이라는  파라미터를 갖는 Attribute로 정의 되어있습니다.  이 string 파라미터는 client 사이드의 Hub이름입니다.

 The Hub as the name suggests keeps track of the ‘subscribers’ and ‘publishes’ or broadcasts the messages that are passed to it by the subscribers.

위에 코드에서 Send메서드는 자바스크립트를 통해 웹페이지에서 호출됩니다. SignalR프래임워크는 적절한 연결을 담당합니다.

Hub가 제공하는 이벤트에 관심있는 각 클라이어트들은 addMessage기능을 구현합니다. 그래서 Hub이 구동될때 모든 클라이언트들은 그 이벤트들 핸들링하게 됩니다.

On the Client Side

Review.cshtml열고 다음을 추가해 주세요.

review-references

Jquery와 SignalR은 nuget package에서 설치될수 있습니다. 그라나 Json2.min.js는 그렇지 않습니다.
https://github.com/douglascrockford/JSON-js이 사이트에서 꼭 다운로드 하세요.이 라이브러리는 Douglas Crockford가 작성하였고 이것은 public domain 라이센스입니다. minified version은 http://code.google.com/p/webscan/source/browse/trunk/ui/js/third-party/json2.min.js?r=80 에서 다운로드 가능합니다.

위에 참조추가에서 ‘/signalr/hubs’참조는 녹색으로 라인이 있는데 그 이유는 이 스크립트는 디자인타임에 존재하는것이 아니라 런타임시에 제너레이트 되기 때문입니다.

Bringing Diff-Match-Patch into the party
우리는 Neil Fraiser’s라는 훌륭한 모듈을 사용할것입니다.(다운사이트 http://code.google.com/p/google-diff-match-patch/) 이 사이트에는 서버사이트또는 클라이언트 자바스크립트의 유용한 오픈 라이브러리들이 있는 곳입니다. 저자는 클라이언트의 모든 작업들을 하려고 결심했고 그래서 저자는 아래의 레퍼런스들을 Review.cshtml에 참조하였습니다.
mvc-review-reference

placeholder(sessionId를 저장)를 Review.cshtml에 추가하고 이 SessionId는 어떤 클라이언트가 요청을 했는지 식별하기 위한 아이디를 사용할 것입니다.

session-id

Hooking up the hub and the publish handlers

Review.cshtml에 다음 자바스크립트 코드를 추가해 주세요
publish-handlers

위의 주석은 간단한 개인적 설명이고 이벤트가 발생하는 순서는 다음과 같습니다.
  1. 두명의 클라이언트가 같은 BlogPost를 검토합니다.
  2. 한사람이 BlogPost의 기사를 수정합니다.(이 작업은 'Send'로 클라이언트의 세션아이디와함께 Hub으로 보내집니다.)
  3. Hub는 단순히 모든 클라이언트의 ‘addMessage’의 함수를 호출하게 됩니다.
  4. 이제 두명의 클라이언트는 addMessage 신호를 받습니다. 오직 한사람 sesseionId가 다른 사람많이 다음 작업이 이루어집니다.

Other Miscellaneous changes

Update _Layout.cshtml ‘s jquery script reference to the version you have.
Make things pretty by changing the default title of the app from ‘My MVC Application’ in the _Layout.cshtml to something nicer.
Change the Index.cshtml and update the header from ‘BlogBody’ to ‘Article’
Change the Global.asax ‘s RegisterRoutes method to navigate to the BlogPost’s Index directly

register-routes

Step 7: Let it Roll

Run the application and create a new Post. Save it. Your Index page should look something like the following

mvc-signalr-demo

Click on Review to go the review page. Press Ctrl+N to fire up a new browser instance with same page. Hit F5 to update session Id in the new Browser instance.

Line up the browsers side by side. Type in one and watch the other one change.

mvc-signalr-sync

Conclusion

SignalR is a powerful and easy to use framework that enables permanent connections and Asynchronous signaling in ASP.NET. Its potential uses include but not limited to
  • Collaborative editing tools like the one we saw here.
  • Highly dynamic apps where certain changes can be pushed in near real time for example, a Cart can signal a purchase completion enabling dynamic updates of ‘stock numbers’ for end users
  • News tickers with real-time feeds and many many more.
Long-polling is not a new thing, however now we have a fantastic abstraction to use in ASP.NET.

So what will You do with SignalR?

Full Disclosure: I have reproduced parts of this article from an article on the same topic in my personal blog.

The entire source code of this article can be downloaded over here