Sunday, February 26, 2017

Configuring React in Visual Studio 2015 / ASP.NET Core with Webpack and NodeJs/Typescript tools

So I haven't blogged in a while...or much ever to be honest...but it looks like it's been 6 years...yikes! Guess its time for a new post.

I'm working on a side project and decided to use React for the front end. My project is an ASP.NET Core Web Application running against .NET framework. It wasn't too hard to get react working initially. First I added it as a Bower package, referenced the react.js files in my Layout view, added a couple of NPM packages for Babel and React and configured a gulp task to transpile my JSX files into javascript.  Took and hour or two to figure it all out but it worked. Not too bad to get a Hello World up and running.

BUT BUT BUT then I tried to split up my React components and import/export them as modules and this is where everything went to hell. My code still compiled with Gulp, but i got an error in the browser.

require is not defined

OK. I realized I needed to use a module loader to get this thing working the way I want and split up my components. Now let me preface this post by saying I don't have a lot of experience with Gulp or Babel or Webpack or Node or Browserify or Grunt or any of the other 5,000 front end Javascript precompilation/bundling/task running programs. But it wasn't to hard to get React up and running, it shouldn't be too hard to get the modules working either, right? Wrong.

It took me about 2 days of absolute frustration to get the JSX files working in Visual Studio the way I wanted. My hope here is to save someone else the time, as there seems to be little on the web about getting React working correctly in Visual Studio.

First let me tell you what didn't work. I tried to get the modules working using Gulp since that is what is already running by default in my project. There may be a way to do this...but I couldn't figure it out. I tried using some Browserify and Rollup plug-ins and some other stuff in my Gulp script to no avail. The documentation on this stuff is sparse and there are 500 npm packages and plugins that might or might not work or are deprecated, and for most of them I couldn't find a good recipe that worked how I wanted with my project.

I also tried using Typescript TSX files. I wasn't too keen on this as the tsx syntax is a little different like forcing you to use a generic version of React.Component with a Typescript interface. Frankly I just wanted to use the vanilla syntax, and even though it kind-of worked for a simple file i was still getting strange errors on the import statements in the text editor. I tried every possible combination of settings in the typescript config file to no avail. So, this is how I finally got everything playing nicely.

Step 1

Make sure you have the following two Visual Studio extensions installed. These packages will give you better intellisense and tooling for your javascript coding.  I'm not entirely sure both are required to make this work, but I couldn't get some of the module errors to go away until I had them installed and started using the respective editors.

Node JS Tools for Visual Studio

Typescript for Visual Studio 2015

Step 2

Next go to Tools -> Options -> Text Editor -> File Extension and set .jsx files to use the TypeScript editor. This is the only way I could get the module import/export errors to disappear in the text editor. I also set my js files to use the Node editor.



Step 3

Were going to use Webpack to build the JSX files and do the module loading. The thing is...there is no webpack support in the default Core Web App project so we have to add everything manually. The wonderful article below helped me get over the hump, although its not specific to .NET so I had to tweak a couple of things.

Setting up React with Babel and Webpack

I installed Webpack with

npm install -g webpack@2.1.0-beta21

Why not use the latest version? Well...I tried that initially and maybe it will work with the configuration in the tutorial link above, but it did NOT work with some other examples I found such as this one. Apparently there are breaking changes in the latest version of Webpack that conflict with several of the configs I found online. So feel free to try the latest version at your own risk, but 2.1.0-beta21 worked for me so I'm sticking with that for now.

Step 4

Add the following npm packages to your package.json file. Also "path" if its not already there. These will be used by Webpack. (I just add these in my package.json but you can use the command line as well.)

npm i babel-loader babel-preset-es2015 babel-preset-react -S

Step 5

Create a webpack config in your root project directory. This file is called

webpack.config.js

I configured mine as follows. In my root web project directory I added a folder called "app" and one below that called "components" for my React components. I also added an "app" folder in wwwroot. This configuration will build "./app/index.jsx" to ".'wwwroot/app/bundle.js".

var path = require('path');
 
var BUILD_DIR = path.resolve(__dirname, 'wwwroot/app');
var APP_DIR = path.resolve(__dirname, 'app');
 
var config = {
    entry: APP_DIR + '/index.jsx',
    output: {
        path: BUILD_DIR,
        filename: 'bundle.js'
    },
    module : {
        loaders : [
            {
                test : /\.jsx?/,
                include : APP_DIR,
                loader : 'babel'
            }
        ]
    }
};
 
module.exports = config;

Step 6

Add a file called .babelrc in the root projectd directory. This is the babel configuration. I used the following code from the tutorial linked above.

{
  "presets" : ["es2015""react"]
}

Step 7

Create your JSX files. At this point you have a couple of options since module loading is now set up. One is you can just add script references to React to your HTML from the wwwroot/lib folder from a Bower install. Then you just have to import other React components to your JSX files.  Make sure you give a relative path to your other JSX components as they aren't NPM installs and otherwise Webpack will not know where to look.




The other option is to install the React NPM packages and then import the React and ReactDOM modules into your JSX files. The libraries will be compiled out to your bundle.js files and then you don't need the react script references or the Bower install.



Step 8

Open a command prompt and navigate to your project directory. Run the Webpack command below. This will build your JSX to a bundle.js file in wwwroot.

>webpack -d

Step 9

Add the bundle.js file to your HTML.

@section Scripts
{
    
    
    <script src="~/app/bundle.js"></script>
   
}

Step 10

Run your project. Boom! Your React app should be up and running!

Conclusion

At this point you would have to run the webpack build every time you change a JSX file which is a little annoying. However the React tutorial shows how to set up a watch with NPM to get it to auto-build on file changes.

Let me know if this doesn't work for you or if you have any other suggestions. I'm still not getting any JSX intellisense, but at least I'm not getting build errors. I would love to know how to get this working with Gulp so that I only have to deal with one task runner. Below is a screenshot of my package.json to show the versions I am using in my project. If this setup doesn't work for anyone happy to edit the post or see if I can help diagnose the issue.






















Thursday, February 3, 2011

ASP.NET MVC3 Html.RenderAction infinite loop / stackoverflow

I have started learning some Asp.net MVC and recently switched over to the MVC3 Razor view engine. I was trying to generate a menu from a controller action and use it on my Layout page so that it was viewable to all pages. So I created a NavController and a Menu() action method with corresponding view. For simplicity, the action just passed an IEnumerable model to the view, which it used to form an unordered list of action links.

I then used Html.RenderAction in the Layout page to render the menu. To my surprise, I got a stack overflow. Upon debugging i realized that it was looping over the action method again and again.

It turns out...and I'm assuming this is Razor specific but have no idea... that if you return a ViewResult from your action method, it will reference the Layout page and call the RenderAction method again. Which returns another ViewResult and references the Layout page again. And again. And again. Until it causes a crash.

The solution was to return a PartialViewResult from the Menu() action, instead of ViewResult. This eliminated the infinite loop and correctly rendered my menu.


Tuesday, July 28, 2009

WCF Authorization with WindowsIdentity.GetCurrent()

Well, in a nutshell this doesn’t work. Our application has some role based security that depends on a AD role to run certain methods. One of the users was having no problems with the security model on the client side, but couldn’t access certain methods behind the WCF service. We wasted a few hours trying to figure out why our WCF service was not correctly recognizing this user’s role. With the help of some added logging we finally figured out that it wasn’t recognizing the user or the role.

Even though our web server is an internal server in the same domain as the client app, the Name property on our windows identity kept returning “NT AUTHORITY\NETWORK SERVICE”, regardless of the fact that we had set up the WCF binding to use Windows authentication. There are so many configuration options for WCF most of the debugging time was wasted trying to figure out what we had configured improperly, or what we needed to do to get the impersonation to work. I finally realized that configuration wasn’t the issue.

To correctly get the windows identity, or the user name and role, you need to either use the ServiceSecurityContext class or pull the name directly from the thread. This is somewhat obvious if you think about the whole security model and how WCF is doing the impersonation, but still it could throw you for a loop if you’re not used to using user security with WCF. It definately caused us a mile headache for a few hours. Solution below.

Web service bindings configuration:


<bindings>


  <wsHttpBinding>


    <binding name="secureBinding">


      <security mode="Message">


        <message clientCredentialType="Windows" />


      </security>


    </binding>


  </wsHttpBinding>


</bindings>





C# code:


WindowsIdentity sscIdentity= ServiceSecurityContext.Current.WindowsIdentity;


//OR


WindowsIdentity threadIdentity = (WindowsIdentity)Thread.CurrentPrincipal.Identity;


Thursday, July 23, 2009

The breakpoint will not currently be hit. No symbols have been loaded ... CHECK YOUR PROCESSES!

Ok its been a while since i posted on this blog but i'm going to try and start doing better. It doesn't help that the web filter at my new job blocks the blogger.com site. By the time i get home my thoughts seem to dissipate as i take care of my 18 month old till bedtime. Anyway...

So today i got the infamous "The breakpoint will not currently be hit." message in my project. To be specific, the project I'm working on is an n-tier enterprise app containing some C# interop user controls that are gradually replacing the functionality in an older VB6 application. Basically when debugging i would run the VB6 application, attach the the VB6.exe process from visual studio 2008, and break in the user control as needed.

Well, two days ago i started getting the "No Symbols" error. I tried all the solutions that you will find when googling the problem: deleting bin directories, rebuilding the project, playing with configuration properties etc etc. Basically crossing my fingers and praying it would go away. But it didnt.

Research led me to discover the "Modules" window, which is available from the debug menu when debugging. This is where it gets interesting. The modules window, as you will find discussed in many blog posts and forums, shows if the debug symbols have been successfully loaded for your assemblies. It also allows you to load symbols manually and see what location items are being loaded from. The problem is, the dlls i was trying to break in weren't even in the modules window. How do i get them there??

What i came to realize (and this may be apparent to veteran programmers, but it wasn't to me) is that the Modules window shows all of the assemblies that are loaded into the processes that visual studio is attached to. I needed to see exactly what assemblies were loaded as i was running my project, so i downloaded the Process Explorer app from Technet (link below). This handy tool lets you select a running process and view all of the assemblies in that process. Sure enough i booted up VB6, ran the tool, and my project assemblies weren't there!

This is when the light came on in my dense skull. How could the VB6 run my interop controls if it hadn't loaded the assemblies?? It couldn't. Once i clicked on the form containing the controls, my project dlls showed up in the process explorer window. It wasn't loading the assemblies until they were needed. Once the process had the right dlls loaded, i could attach to VB6 from visual studio and set the breakpoints. (Important to note, if you have this similar issue you must detach and reattach the debugger for it grab the just loaded dlls.) Furthermore, once the assemblies are loaded the first time you can start and re-start the VB6 project and they will remail loaded.

You may notice a similar issue if you are running a web or WCF service locally while debugging. When i started working on the project i could set a break anywhere, but once i started having this issue, i had to manually go in and attach to the WCF service to set breaks in the bottom tiers. I've yet to figure out exactly what changed that started the whole "No Symbols" problem, and i probably won't pursue it at this point...i'm just happy to be able to finish my work.



http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

Wednesday, December 10, 2008

Event code: 3004 File Upload too large

I have a custom application i've been working on and i was trying to upload a 5MB file with an asp fileupload control. This was giving me the dreaded "Internet Explorer Cannot Display the web page." error. I soon realized that the file size was the issue and added an httpruntime element to my web config file.

httpRuntime maxRequestLength="10240"

Ok, so i should be able to upload 10 meg files now. No luck. No matter how i configured the httpruntime element i kept getting the same error. IIS couldn't have been the issue because i was running the app from Visual Studio. I had been stumped for hours when i accidently figured out the issue.

We had several settings in our system.web section of the web config. I put the httpruntime tag at the end of the section. For some reason the application was not seeing it here. When i moved it directly after the tag, the file upload worked fine. I have no idea was causing the tag to work incorrectly or why the location mattered. Any thoughts feel free to share.

Frustrating. Thanks Microsoft.

Thursday, September 25, 2008

gridItem.OwnerTableView.DataKeyValues NullReferenceException

GridDataItem gridItem = e.Item as GridDataItem;
gridItem["ColumnName"].ToolTip = "CustomerID: " + gridItem.OwnerTableView.DataKeyValues[gridItem.ItemIndex][ "ColumnName2"].ToString();

While trying to assign a tooltip to a Telerik Radgrid cell with the above code (courtesy of the Telerik documentation) I kept getting a NullReferenceException. For some reason i could not ascertain the gridItem.ItemIndex kept coming up 0. I circumvented the problem by casting the GridDataItem to a DataRowView and using the named index of the row to get the value. Not sure why Telerik tried to make it so complicated...


GridDataItem gridItem = e.Item as GridDataItem;
DataRowView row = (DataRowView)gridItem.DataItem;
gridItem["ColumnName"].ToolTip = row["ColumnName2"].ToString();