title: Cannot Use @Html.React in Layout Razor View File
body: <p>It appears that after solving my previous issue with CSS, I've come into another roadblock. I was trying to do the "Optimization: Server-side rendering" exercise from the reactjs.net website. Unfortunately, problem - I can't use the "@Html.React" method in the razor view to pass the Comment Box model. I've tried several what were probably unnecessary imports, and ensuring that my ReactConfig file was updated so that I could use that code. Can anyone tell me what I'm missing here?</p>
  
  <p>ReactConfig.cs:</p>
  
  <pre><code>using React;
  
  [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(ReactExamplePractice.ReactConfig), "Configure")]
  
  namespace ReactExamplePractice
  {
      using React;
      public static class ReactConfig
      {
          public static void Configure()
          {
              // If you want to use server-side rendering of React components, 
              // add all the necessary JavaScript files here. This includes 
              // your components as well as all of their dependencies.
              // See http://reactjs.net/ for more information. Example:
              //ReactSiteConfiguration.Configuration
              //  .AddScript("~/Scripts/First.jsx")
              //  .AddScript("~/Scripts/Second.jsx");
              ReactSiteConfiguration.Configuration = new ReactSiteConfiguration()
                  .AddScript("~/Scripts/react/Tutorial.jsx");
              //ReactSiteConfiguration.Configuration
              //    //.AddScript("~/js/remarkable.min.js")
              //    .AddScript("~/Scripts/react/Tutorial.jsx");
              // If you use an external build too (for example, Babel, Webpack,
              // Browserify or Gulp), you can improve performance by disabling 
              // ReactJS.NET's version of Babel and loading the pre-transpiled 
              // scripts. Example:
              //ReactSiteConfiguration.Configuration
              //  .SetLoadBabel(false)
              //  .AddScriptWithoutTransform("~/Scripts/bundle.server.js")
          }
      }
  }
  </code></pre>
  
  <p>BundleConfig.cs:</p>
  
  <pre><code>using System.Web;
  using System.Web.Optimization;
  using System.Web.Optimization.React;
  
  namespace ReactExamplePractice
  {
      public class BundleConfig
      {
          // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
          public static void RegisterBundles(BundleCollection bundles)
          {
              bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                          "~/Scripts/jquery-{version}.js"));
  
              bundles.Add(new BabelBundle("~/bundles/main").Include(
                  "~/Scripts/react/Tutorial.jsx"
              ));
  
              // Forces files to be combined and minified in debug mode
              // Only used here to demonstrate how combination/minification works
              // Normally you would use unminified versions in debug mode.
              BundleTable.EnableOptimizations = true;
  
              bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                          "~/Scripts/jquery.validate*"));
  
              // Use the development version of Modernizr to develop with and learn from. Then, when you're
              // ready for production, use the build tool at https://modernizr.com to pick only the tests you need.
              bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                          "~/Scripts/modernizr-*"));
  
              bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                        "~/Scripts/bootstrap.js"));
  
              bundles.Add(new StyleBundle("~/Content/css").Include(
                        "~/Content/bootstrap.css",
                        "~/Content/site.css"));
          }
      }
  }
  </code></pre>
  
  <p>_Layout.cshtml:</p>
  
  <pre><code>@using System.Web.Optimization.React;
  @using React;
  &lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
      &lt;meta charset="utf-8" /&gt;
      &lt;meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"&gt;
  
      @*&lt;environment exclude="Development"&gt;
          &lt;link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous"&gt;
      &lt;/environment&gt;*@
  
      &lt;environment exclude="Development"&gt;
          &lt;link href="~/Content/bootstrap.min.css" rel="stylesheet" /&gt;
      &lt;/environment&gt;
  
      &lt;title&gt;@ViewData["Title"] - ASP.NET Core Pages Webpack&lt;/title&gt;
      @model IEnumerable&lt;ReactExamplePractice.Models.CommentModel&gt;
          @{ 
              Layout = null;
          }
  &lt;/head&gt;
  &lt;body&gt;
      &lt;div class="container"&gt;
          &lt;nav class="bg-dark mb-4 navbar navbar-dark navbar-expand-md"&gt;
              &lt;a asp-page="/Index" class="navbar-brand"&gt;
                  &lt;em&gt;ASP.NET Core Pages Webpack&lt;/em&gt;
              &lt;/a&gt;
              &lt;button aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#topNavbarCollapse" data-toggle="collapse" type="button"&gt;
                  &lt;span class="navbar-toggler-icon"&gt;&lt;/span&gt;
              &lt;/button&gt;
              &lt;div class="collapse navbar-collapse" id="topNavbarCollapse"&gt;
                  &lt;ul class="mr-auto navbar-nav"&gt;
                      &lt;li class="nav-item"&gt;
                          @Html.ActionLink("Application Name", "Index", "Default", new { area = "" }, new { @class = "navbar-brand" })
                      &lt;/li&gt;
                      &lt;li class="nav-item"&gt;
                          &lt;a asp-page="/About" class="nav-link"&gt;About&lt;/a&gt;
                      &lt;/li&gt;
                      &lt;li class="nav-item"&gt;
                          &lt;a asp-page="/Contact" class="nav-link"&gt;Contact&lt;/a&gt;
                      &lt;/li&gt;
                  &lt;/ul&gt;
                  &lt;ul class="navbar-nav"&gt;
                      &lt;li class="nav-item"&gt;
                          &lt;a class="nav-link" href="https://twitter.com/damien_bod"&gt;
                              &lt;img height="30" src="assets/damienbod.jpg" /&gt;
                          &lt;/a&gt;
                      &lt;/li&gt;
                  &lt;/ul&gt;
              &lt;/div&gt;
          &lt;/nav&gt;
  
      &lt;/div&gt;
  
      &lt;partial name="_CookieConsentPartial" /&gt;
  
      &lt;div class="container body-content"&gt;
          @RenderBody()
  
          &lt;hr /&gt;
          &lt;footer&gt;
              &lt;p&gt;&amp;copy; 2018 - ASP.NET Core Pages Webpack Bootstrap 4&lt;/p&gt;
          &lt;/footer&gt;
      &lt;/div&gt;
  
      &lt;environment exclude="Development"&gt;
          &lt;!-- Optional JavaScript --&gt;
          &lt;!-- jQuery first, then Popper.js, then Bootstrap JS --&gt;
          @*&lt;script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"&gt;&lt;/script&gt;
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"&gt;&lt;/script&gt;
          &lt;script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"&gt;&lt;/script&gt;*@
          &lt;script src="~/Scripts/jquery-3.3.1.slim.min.js"&gt;&lt;/script&gt;
          &lt;script src="~/Scripts/popper.min.js"&gt;&lt;/script&gt;
          &lt;script src="~/Scripts/bootstrap.min.js"&gt;&lt;/script&gt;
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"&gt;&lt;/script&gt;
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"&gt;&lt;/script&gt;
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"&gt;&lt;/script&gt;
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"&gt;&lt;/script&gt;
          @Scripts.Render("~/bundles/main");
          @*&lt;script src="@Url.Content("~/Scripts/react/Tutorial.jsx")"&gt;&lt;/script&gt;*@
      &lt;/environment&gt;
  
      @RenderSection("Scripts", required: false)
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>DefaultController.cs:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using System.Web.Mvc;
  using System.Web.UI;
  using ReactExamplePractice.Models;
  using System.Web.Optimization.React;
  using React;
  
  namespace ReactExamplePractice.Controllers
  {
      public class DefaultController : Controller
      {
          private static readonly IList&lt;CommentModel&gt; _comments;
  
          static DefaultController()
          {
              _comments = new List&lt;CommentModel&gt;
              {
                  new CommentModel
                  {
                      Id = 1,
                      Author = "Daniel Lo Nigro",
                      Text = "Hello ReactJS.NET World!"
                  },
                  new CommentModel
                  {
                      Id = 2,
                      Author = "Pete Hunt",
                      Text = "This is one comment"
                  },
                  new CommentModel
                  {
                      Id = 3,
                      Author = "Jordan Walke",
                      Text = "This is *another* comment"
                  },
              };
          }
  
          [OutputCache(Location = OutputCacheLocation.None)]
          public ActionResult Comments()
          {
              return Json(_comments, JsonRequestBehavior.AllowGet);
          }
  
          [HttpPost]
          public ActionResult AddComment(CommentModel comment)
          {
              //Create a fake ID for this comment or something
              comment.Id = _comments.Count + 1;
              _comments.Add(comment);
              return Content("Success :)");
          }
  
          // GET: Default
          public ActionResult Index()
          {
              return View();
          }
      }
  }
  </code></pre>
  
  <p>Tutorial.jsx:</p>
  
  <pre><code>class CommentBox extends React.Component {
      constructor(props) {
          super(props);
          this.state = { data: this.props.initialData };
          this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
      }
  
      loadCommentsFromServer() {
          const xhr = new XMLHttpRequest();
          xhr.open('get', this.props.url, true);
          xhr.onload = () =&gt; {
              const data = JSON.parse(xhr.responseText);
              this.setState({ data: data });
          };
          xhr.send();
      }
  
      handleCommentSubmit(comment) {
          const comments = this.state.data;
          // Optimistically set an id on the new comment. It will be replaced by an
          // use a more robust system for ID generation.
          // id generated by the server. In a production application you would likely
          comment.Id = comments.length + 1;
          const newComments = comments.concat([comment]);
          this.setState({data: newComments});
  
          const data = new FormData();
          data.append('Author', comment.Author);
          data.append('Text', comment.Text);
  
          const xhr = new XMLHttpRequest();
          xhr.open('post', this.props.submitUrl, true);
          xhr.onload = () =&gt; this.loadCommentsFromServer();
          xhr.send(data);
      }
  
      componentDidMount() {
          window.setInterval(() =&gt; this.loadCommentsFromServer(), this.props.pollInterval);
      }
  
      render() {
          return (
              &lt;div className="commentBox"&gt;
                  &lt;h1&gt;Comments&lt;/h1&gt;
                  &lt;CommentList data={this.state.data} /&gt;
                  &lt;CommentForm onCommentSubmit={this.handleCommentSubmit} /&gt;
              &lt;/div&gt;
          );
      }
  }
  
  class CommentList extends React.Component {
      render() {
          const commentNodes = this.props.data.map(comment =&gt; (
              &lt;Comment author={comment.Author} key={comment.Id}&gt;
                  {comment.Text}
              &lt;/Comment&gt;
              ));
          return (
              &lt;div className="commentList"&gt;
                  {commentNodes}
        &lt;/div&gt;
          );
      }
  }
  
  class CommentForm extends React.Component {
      constructor(props) {
          super(props);
          this.state = { author: '', text: '' };
          this.handleAuthorChange = this.handleAuthorChange.bind(this);
          this.handleTextChange = this.handleTextChange.bind(this);
          this.handleSubmit = this.handleSubmit.bind(this);
      }
  
      handleAuthorChange(e) {
          this.setState({author: e.target.value});
      }
  
      handleTextChange(e) {
          this.setState({ text: e.target.value });
      }
  
      handleSubmit(e) {
          e.preventDefault();
          const author = this.state.author.trim();
          const text = this.state.text.trim();
          if (!text || !author) {
              return;
          }
          this.props.onCommentSubmit({Author: author, Text: text});
          this.setState({ author: '', text: '' });
      }
  
      render() {
          return (
              &lt;form className="commentForm" onSubmit={this.handleSubmit} &gt;
                  &lt;input type="text" placeholder="Your name" value={this.state.author} onChange={this.handleAuthorChange} /&gt;
                  &lt;input type="text" placeholder="Post something here!" value={this.state.text} onChange={this.handleTextChange} /&gt;
                  &lt;input type="submit" value="Post" /&gt;
        &lt;/form&gt;
          );
      }
  }
  
  class Comment extends React.Component {
      rawMarkup() {
          const md = new (global.Remarkable || window.Remarkable)();
          const rawMarkup = md.render(this.props.children.toString());
          return { __html: rawMarkup };
      }
      render() {
          return (
              &lt;div className="comment"&gt;
                  &lt;h2 className="commentAuthor"&gt;
                      {this.props.author}
                  &lt;/h2&gt;
                  &lt;span dangerouslySetInnerHTML={this.rawMarkup()} /&gt;
              &lt;/div&gt;
          );
      }
  }
  
  class HelloWorld extends React.Component {
      render() {
          return (
              &lt;div&gt;
                  &lt;h1&gt; Hello World React JS! &lt;/h1&gt;
      &lt;/div&gt;)  
                      }  
                  }
  
  //ReactDOM.render(
  //    &lt;CommentBox url="/comments" submitUrl="/comments/new"  pollInterval={2000} /&gt;,
  //    document.getElementById('content')
  //);
  </code></pre>
  
  <p>Any help/insight on this would be greatly appreciated. Thanks a ton in advance!</p>