{"action":"created","comment":{"url":"https://api.github.com/repos/aspnet/Diagnostics/pulls/comments/35024995","id":35024995,"diff_hunk":"@@ -182,31 +188,103 @@ private StackFrame StackFrame(Chunk line)\n \n             int lineNumber = line.ToInt32();\n \n-            return string.IsNullOrEmpty(file)\n-                ? LoadFrame(string.IsNullOrEmpty(function) ? line.ToString() : function, string.Empty, 0)\n-                : LoadFrame(function, file, lineNumber);\n+            if (string.IsNullOrEmpty(file))\n+            {\n+                return GetStackFrame(\n+                    string.IsNullOrEmpty(function) ? line.ToString() : function,\n+                    file: string.Empty,\n+                    lineNumber: 0,\n+                    fileProvider: _options.FileProvider,\n+                    sourceCodeLineCount: _options.SourceCodeLineCount);\n+            }\n+            else\n+            {\n+                return GetStackFrame(function, file, lineNumber, _options.FileProvider, _options.SourceCodeLineCount);\n+            }\n         }\n \n-        private StackFrame LoadFrame(string function, string file, int lineNumber)\n+        internal static StackFrame GetStackFrame(\n+            string function,\n+            string file,\n+            int lineNumber,\n+            IFileProvider fileProvider,\n+            int sourceCodeLineCount)\n         {\n             var frame = new StackFrame { Function = function, File = file, Line = lineNumber };\n+\n+            if (string.IsNullOrEmpty(file))\n+            {\n+                return frame;\n+            }\n+\n+            IEnumerable<string> lines = null;\n             if (File.Exists(file))\n             {\n-                var code = File.ReadLines(file);\n-                ReadFrameContent(frame, code, lineNumber, lineNumber);\n+                lines = File.ReadLines(file);\n             }\n+            else\n+            {\n+                // Handle relative paths and embedded files\n+                var fileInfo = fileProvider.GetFileInfo(file);\n+                if (fileInfo.Exists)\n+                {\n+                    // ReadLines doesn't accept a stream. Use ReadLines as its more efficient\n+                    // relative to reading lines via stream reader\n+                    if (!string.IsNullOrEmpty(fileInfo.PhysicalPath))\n+                    {\n+                        lines = File.ReadLines(fileInfo.PhysicalPath);\n+                    }\n+                    else\n+                    {\n+                        lines = GetLines(fileInfo.CreateReadStream());\n+                    }\n+                }\n+            }\n+\n+            if (lines != null)\n+            {\n+                GetErrorCodeBlock(frame, lines, lineNumber, sourceCodeLineCount);\n+            }\n+\n             return frame;\n         }\n \n-        private void ReadFrameContent(StackFrame frame,\n-                                      IEnumerable<string> code,\n-                                      int startLineNumber,\n-                                      int endLineNumber)\n+        private static void GetErrorCodeBlock(\n+            StackFrame frame,\n+            IEnumerable<string> allLines,\n+            int errorLineNumberInFile,\n+            int sourceCodeLineCount)\n+        {\n+            // Get the line boundaries in the file to be read and read all these lines at once into an array.\n+            // This will cause the backing stream to be closed.\n+            var preErrorLineNumberInFile = Math.Max(errorLineNumberInFile - sourceCodeLineCount, 1);\n+            var postErrorLineNumberInFile = errorLineNumberInFile + sourceCodeLineCount;\n+            var codeBlock = allLines\n+                .Skip(preErrorLineNumberInFile - 1)\n+                .Take(postErrorLineNumberInFile - preErrorLineNumberInFile + 1)\n+                .ToArray();\n+\n+            // get the position of the error line in the array","path":"src/Microsoft.AspNet.Diagnostics/ErrorPageMiddleware.cs","position":132,"original_position":132,"commit_id":"8141eb6cf116c3a97b2779dd3953b03b0aac486a","original_commit_id":"8141eb6cf116c3a97b2779dd3953b03b0aac486a","user":{"login":"NTaylorMullen","id":2008729,"avatar_url":"https://avatars.githubusercontent.com/u/2008729?v=3","gravatar_id":"","url":"https://api.github.com/users/NTaylorMullen","html_url":"https://github.com/NTaylorMullen","followers_url":"https://api.github.com/users/NTaylorMullen/followers","following_url":"https://api.github.com/users/NTaylorMullen/following{/other_user}","gists_url":"https://api.github.com/users/NTaylorMullen/gists{/gist_id}","starred_url":"https://api.github.com/users/NTaylorMullen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NTaylorMullen/subscriptions","organizations_url":"https://api.github.com/users/NTaylorMullen/orgs","repos_url":"https://api.github.com/users/NTaylorMullen/repos","events_url":"https://api.github.com/users/NTaylorMullen/events{/privacy}","received_events_url":"https://api.github.com/users/NTaylorMullen/received_events","type":"User","site_admin":false},"body":"Variable name says this.","created_at":"2015-07-20T18:10:39Z","updated_at":"2015-07-20T18:10:39Z","html_url":"https://github.com/aspnet/Diagnostics/pull/158#discussion_r35024995","pull_request_url":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158","_links":{"self":{"href":"https://api.github.com/repos/aspnet/Diagnostics/pulls/comments/35024995"},"html":{"href":"https://github.com/aspnet/Diagnostics/pull/158#discussion_r35024995"},"pull_request":{"href":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158"}}},"pull_request":{"url":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158","id":40263061,"html_url":"https://github.com/aspnet/Diagnostics/pull/158","diff_url":"https://github.com/aspnet/Diagnostics/pull/158.diff","patch_url":"https://github.com/aspnet/Diagnostics/pull/158.patch","issue_url":"https://api.github.com/repos/aspnet/Diagnostics/issues/158","number":158,"state":"open","locked":false,"title":"[Fixes #157] ErrorPage middleware doesn't show source code lines of R…","user":{"login":"kichalla","id":6559784,"avatar_url":"https://avatars.githubusercontent.com/u/6559784?v=3","gravatar_id":"","url":"https://api.github.com/users/kichalla","html_url":"https://github.com/kichalla","followers_url":"https://api.github.com/users/kichalla/followers","following_url":"https://api.github.com/users/kichalla/following{/other_user}","gists_url":"https://api.github.com/users/kichalla/gists{/gist_id}","starred_url":"https://api.github.com/users/kichalla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kichalla/subscriptions","organizations_url":"https://api.github.com/users/kichalla/orgs","repos_url":"https://api.github.com/users/kichalla/repos","events_url":"https://api.github.com/users/kichalla/events{/privacy}","received_events_url":"https://api.github.com/users/kichalla/received_events","type":"User","site_admin":false},"body":"…azor files\r\n\r\n@NTaylorMullen @Tratcher","created_at":"2015-07-17T19:21:27Z","updated_at":"2015-07-20T18:10:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f174be6091346c9b13868b8cfcf23a802a67095b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158/commits","review_comments_url":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158/comments","review_comment_url":"https://api.github.com/repos/aspnet/Diagnostics/pulls/comments{/number}","comments_url":"https://api.github.com/repos/aspnet/Diagnostics/issues/158/comments","statuses_url":"https://api.github.com/repos/aspnet/Diagnostics/statuses/8141eb6cf116c3a97b2779dd3953b03b0aac486a","head":{"label":"aspnet:kiran/razor-sourcecode-lines","ref":"kiran/razor-sourcecode-lines","sha":"8141eb6cf116c3a97b2779dd3953b03b0aac486a","user":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"repo":{"id":17548048,"name":"Diagnostics","full_name":"aspnet/Diagnostics","owner":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aspnet/Diagnostics","description":"Middleware to show diagnostic information about a site, including error pages.","fork":false,"url":"https://api.github.com/repos/aspnet/Diagnostics","forks_url":"https://api.github.com/repos/aspnet/Diagnostics/forks","keys_url":"https://api.github.com/repos/aspnet/Diagnostics/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aspnet/Diagnostics/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aspnet/Diagnostics/teams","hooks_url":"https://api.github.com/repos/aspnet/Diagnostics/hooks","issue_events_url":"https://api.github.com/repos/aspnet/Diagnostics/issues/events{/number}","events_url":"https://api.github.com/repos/aspnet/Diagnostics/events","assignees_url":"https://api.github.com/repos/aspnet/Diagnostics/assignees{/user}","branches_url":"https://api.github.com/repos/aspnet/Diagnostics/branches{/branch}","tags_url":"https://api.github.com/repos/aspnet/Diagnostics/tags","blobs_url":"https://api.github.com/repos/aspnet/Diagnostics/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aspnet/Diagnostics/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aspnet/Diagnostics/git/refs{/sha}","trees_url":"https://api.github.com/repos/aspnet/Diagnostics/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aspnet/Diagnostics/statuses/{sha}","languages_url":"https://api.github.com/repos/aspnet/Diagnostics/languages","stargazers_url":"https://api.github.com/repos/aspnet/Diagnostics/stargazers","contributors_url":"https://api.github.com/repos/aspnet/Diagnostics/contributors","subscribers_url":"https://api.github.com/repos/aspnet/Diagnostics/subscribers","subscription_url":"https://api.github.com/repos/aspnet/Diagnostics/subscription","commits_url":"https://api.github.com/repos/aspnet/Diagnostics/commits{/sha}","git_commits_url":"https://api.github.com/repos/aspnet/Diagnostics/git/commits{/sha}","comments_url":"https://api.github.com/repos/aspnet/Diagnostics/comments{/number}","issue_comment_url":"https://api.github.com/repos/aspnet/Diagnostics/issues/comments{/number}","contents_url":"https://api.github.com/repos/aspnet/Diagnostics/contents/{+path}","compare_url":"https://api.github.com/repos/aspnet/Diagnostics/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aspnet/Diagnostics/merges","archive_url":"https://api.github.com/repos/aspnet/Diagnostics/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aspnet/Diagnostics/downloads","issues_url":"https://api.github.com/repos/aspnet/Diagnostics/issues{/number}","pulls_url":"https://api.github.com/repos/aspnet/Diagnostics/pulls{/number}","milestones_url":"https://api.github.com/repos/aspnet/Diagnostics/milestones{/number}","notifications_url":"https://api.github.com/repos/aspnet/Diagnostics/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aspnet/Diagnostics/labels{/name}","releases_url":"https://api.github.com/repos/aspnet/Diagnostics/releases{/id}","created_at":"2014-03-08T18:25:57Z","updated_at":"2015-07-11T00:32:56Z","pushed_at":"2015-07-18T06:38:13Z","git_url":"git://github.com/aspnet/Diagnostics.git","ssh_url":"git@github.com:aspnet/Diagnostics.git","clone_url":"https://github.com/aspnet/Diagnostics.git","svn_url":"https://github.com/aspnet/Diagnostics","homepage":"","size":2718,"stargazers_count":34,"watchers_count":34,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":19,"mirror_url":null,"open_issues_count":21,"forks":19,"open_issues":21,"watchers":34,"default_branch":"dev"}},"base":{"label":"aspnet:dev","ref":"dev","sha":"ab124d2ca0d898db797a3ff114825a84005cb06c","user":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"repo":{"id":17548048,"name":"Diagnostics","full_name":"aspnet/Diagnostics","owner":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aspnet/Diagnostics","description":"Middleware to show diagnostic information about a site, including error pages.","fork":false,"url":"https://api.github.com/repos/aspnet/Diagnostics","forks_url":"https://api.github.com/repos/aspnet/Diagnostics/forks","keys_url":"https://api.github.com/repos/aspnet/Diagnostics/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aspnet/Diagnostics/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aspnet/Diagnostics/teams","hooks_url":"https://api.github.com/repos/aspnet/Diagnostics/hooks","issue_events_url":"https://api.github.com/repos/aspnet/Diagnostics/issues/events{/number}","events_url":"https://api.github.com/repos/aspnet/Diagnostics/events","assignees_url":"https://api.github.com/repos/aspnet/Diagnostics/assignees{/user}","branches_url":"https://api.github.com/repos/aspnet/Diagnostics/branches{/branch}","tags_url":"https://api.github.com/repos/aspnet/Diagnostics/tags","blobs_url":"https://api.github.com/repos/aspnet/Diagnostics/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aspnet/Diagnostics/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aspnet/Diagnostics/git/refs{/sha}","trees_url":"https://api.github.com/repos/aspnet/Diagnostics/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aspnet/Diagnostics/statuses/{sha}","languages_url":"https://api.github.com/repos/aspnet/Diagnostics/languages","stargazers_url":"https://api.github.com/repos/aspnet/Diagnostics/stargazers","contributors_url":"https://api.github.com/repos/aspnet/Diagnostics/contributors","subscribers_url":"https://api.github.com/repos/aspnet/Diagnostics/subscribers","subscription_url":"https://api.github.com/repos/aspnet/Diagnostics/subscription","commits_url":"https://api.github.com/repos/aspnet/Diagnostics/commits{/sha}","git_commits_url":"https://api.github.com/repos/aspnet/Diagnostics/git/commits{/sha}","comments_url":"https://api.github.com/repos/aspnet/Diagnostics/comments{/number}","issue_comment_url":"https://api.github.com/repos/aspnet/Diagnostics/issues/comments{/number}","contents_url":"https://api.github.com/repos/aspnet/Diagnostics/contents/{+path}","compare_url":"https://api.github.com/repos/aspnet/Diagnostics/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aspnet/Diagnostics/merges","archive_url":"https://api.github.com/repos/aspnet/Diagnostics/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aspnet/Diagnostics/downloads","issues_url":"https://api.github.com/repos/aspnet/Diagnostics/issues{/number}","pulls_url":"https://api.github.com/repos/aspnet/Diagnostics/pulls{/number}","milestones_url":"https://api.github.com/repos/aspnet/Diagnostics/milestones{/number}","notifications_url":"https://api.github.com/repos/aspnet/Diagnostics/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aspnet/Diagnostics/labels{/name}","releases_url":"https://api.github.com/repos/aspnet/Diagnostics/releases{/id}","created_at":"2014-03-08T18:25:57Z","updated_at":"2015-07-11T00:32:56Z","pushed_at":"2015-07-18T06:38:13Z","git_url":"git://github.com/aspnet/Diagnostics.git","ssh_url":"git@github.com:aspnet/Diagnostics.git","clone_url":"https://github.com/aspnet/Diagnostics.git","svn_url":"https://github.com/aspnet/Diagnostics","homepage":"","size":2718,"stargazers_count":34,"watchers_count":34,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":19,"mirror_url":null,"open_issues_count":21,"forks":19,"open_issues":21,"watchers":34,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158"},"html":{"href":"https://github.com/aspnet/Diagnostics/pull/158"},"issue":{"href":"https://api.github.com/repos/aspnet/Diagnostics/issues/158"},"comments":{"href":"https://api.github.com/repos/aspnet/Diagnostics/issues/158/comments"},"review_comments":{"href":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158/comments"},"review_comment":{"href":"https://api.github.com/repos/aspnet/Diagnostics/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/aspnet/Diagnostics/pulls/158/commits"},"statuses":{"href":"https://api.github.com/repos/aspnet/Diagnostics/statuses/8141eb6cf116c3a97b2779dd3953b03b0aac486a"}}}}