+ );
+ }
+}
From 49706859da187d8667ec3cac2128fefdcb5099e2 Mon Sep 17 00:00:00 2001
From: Dustin Masters
Date: Wed, 15 Nov 2017 21:51:48 -0800
Subject: [PATCH 2/5] Add tests and update sample
---
src/React.Core/IReactSiteConfiguration.cs | 18 +++++--
src/React.Core/ReactComponent.cs | 6 +--
src/React.Core/ReactSiteConfiguration.cs | 15 +++++-
src/React.Sample.CoreMvc/Startup.cs | 19 +++++---
tests/React.Tests/Core/ReactComponentTest.cs | 51 +++++++++++++++++---
5 files changed, 86 insertions(+), 23 deletions(-)
diff --git a/src/React.Core/IReactSiteConfiguration.cs b/src/React.Core/IReactSiteConfiguration.cs
index 6785d1705..cb6e41dfb 100644
--- a/src/React.Core/IReactSiteConfiguration.cs
+++ b/src/React.Core/IReactSiteConfiguration.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2014-Present, Facebook, Inc.
* All rights reserved.
*
@@ -178,12 +178,20 @@ public interface IReactSiteConfiguration
///
/// Disables server-side rendering. This is useful when debugging your scripts.
///
- IReactSiteConfiguration DisableServerSideRendering();
-
+ IReactSiteConfiguration DisableServerSideRendering();
+
///
- /// Handle an exception caught during server-render of a component.
+ /// An exception handler which will be called if a render exception is thrown.
/// If unset, unhandled exceptions will be thrown for all component renders.
///
- Action HandleRenderException { get; set; }
+ Action ExceptionHandler { get; set; }
+
+ ///
+ /// Sets an exception handler which will be called if a render exception is thrown.
+ /// If unset, unhandled exceptions will be thrown for all component renders.
+ ///
+ ///
+ ///
+ IReactSiteConfiguration SetExceptionHandler(Action handler);
}
}
diff --git a/src/React.Core/ReactComponent.cs b/src/React.Core/ReactComponent.cs
index 7e9e86bb1..cf941ca3b 100644
--- a/src/React.Core/ReactComponent.cs
+++ b/src/React.Core/ReactComponent.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2014-Present, Facebook, Inc.
* All rights reserved.
*
@@ -132,7 +132,7 @@ public virtual string RenderHtml(bool renderContainerOnly = false, bool renderSe
}
catch (JsRuntimeException ex)
{
- if (_configuration.HandleRenderException == null) {
+ if (_configuration.ExceptionHandler == null) {
throw new ReactServerRenderingException(string.Format(
"Error while rendering \"{0}\" to \"{2}\": {1}",
ComponentName,
@@ -140,7 +140,7 @@ public virtual string RenderHtml(bool renderContainerOnly = false, bool renderSe
ContainerId
));
}
- _configuration.HandleRenderException(ex);
+ _configuration.ExceptionHandler(ex);
}
}
diff --git a/src/React.Core/ReactSiteConfiguration.cs b/src/React.Core/ReactSiteConfiguration.cs
index ef10a855a..ee1850610 100644
--- a/src/React.Core/ReactSiteConfiguration.cs
+++ b/src/React.Core/ReactSiteConfiguration.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2014-Present, Facebook, Inc.
* All rights reserved.
*
@@ -306,6 +306,17 @@ public IReactSiteConfiguration DisableServerSideRendering()
/// Handle an exception caught during server-render of a component.
/// If unset, unhandled exceptions will be thrown for all component renders.
///
- public Action HandleRenderException { get; set; }
+ public Action ExceptionHandler { get; set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IReactSiteConfiguration SetExceptionHandler(Action handler)
+ {
+ ExceptionHandler = handler;
+ return this;
+ }
}
}
diff --git a/src/React.Sample.CoreMvc/Startup.cs b/src/React.Sample.CoreMvc/Startup.cs
index 356107449..fb70be38a 100644
--- a/src/React.Sample.CoreMvc/Startup.cs
+++ b/src/React.Sample.CoreMvc/Startup.cs
@@ -20,15 +20,16 @@ namespace React.Sample.CoreMvc
{
public class Startup
{
- public Startup(IHostingEnvironment env)
- {
- // Setup configuration sources.
+ public Startup(IHostingEnvironment env, ILogger logger)
+ {
+ // Setup configuration sources.
var builder = new ConfigurationBuilder().AddEnvironmentVariables();
-
+ Logger = logger;
Configuration = builder.Build();
}
- public IConfiguration Configuration { get; set; }
+ public IConfiguration Configuration { get; set; }
+ public ILogger Logger { get; set; }
// This method gets called by the runtime.
public IServiceProvider ConfigureServices(IServiceCollection services)
@@ -69,8 +70,12 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
{
config
.SetReuseJavaScriptEngines(true)
- .AddScript("~/js/Sample.jsx")
- .SetUseDebugReact(true);
+ .AddScript("~/js/Sample.jsx")
+ .SetExceptionHandler(ex =>
+ {
+ Logger.LogError("React component exception thrown!" + ex.ToString());
+ })
+ .SetUseDebugReact(true);
});
// Add static files to the request pipeline.
diff --git a/tests/React.Tests/Core/ReactComponentTest.cs b/tests/React.Tests/Core/ReactComponentTest.cs
index 8585345cf..e61a9c012 100644
--- a/tests/React.Tests/Core/ReactComponentTest.cs
+++ b/tests/React.Tests/Core/ReactComponentTest.cs
@@ -1,16 +1,18 @@
-/*
+/*
* Copyright (c) 2014-Present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
+ */
+
+using System;
+using JavaScriptEngineSwitcher.Core;
using Moq;
-using Xunit;
using React.Exceptions;
-
+using Xunit;
+
namespace React.Tests.Core
{
public class ReactComponentTest
@@ -190,7 +192,44 @@ public void GeneratesContainerIdIfNotProvided()
var component = new ReactComponent(environment.Object, config.Object, "Foo", null);
Assert.StartsWith("react_", component.ContainerId);
- }
+ }
+
+ [Fact]
+ public void ExceptionThrownIsHandled()
+ {
+ var environment = new Mock();
+ environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true);
+ environment.Setup(x => x.Execute(@"ReactDOMServer.renderToString(React.createElement(Foo, {""hello"":""World""}))"))
+ .Throws(new JsRuntimeException("'undefined' is not an object"));
+
+ var config = new Mock();
+ config.Setup(x => x.UseServerSideRendering).Returns(true);
+ var component = new ReactComponent(environment.Object, config.Object, "Foo", "container")
+ {
+ Props = new { hello = "World" }
+ };
+
+ // Default behavior
+ bool exceptionCaught = false;
+ try
+ {
+ component.RenderHtml();
+ }
+ catch (ReactServerRenderingException)
+ {
+ exceptionCaught = true;
+ }
+
+ Assert.True(exceptionCaught);
+
+ // Custom exception handler set
+ Exception caughtException = null;
+ config.Setup(x => x.ExceptionHandler).Returns(ex => caughtException = ex);
+
+ var result = component.RenderHtml();
+ Assert.Equal(@"", result);
+ Assert.NotNull(caughtException);
+ }
}
}
From ea071c8e152c9c694ac65ec0e4aa7b6f2b9bd6ca Mon Sep 17 00:00:00 2001
From: Dustin Masters
Date: Wed, 15 Nov 2017 21:58:23 -0800
Subject: [PATCH 3/5] Fix newline/whitespace issues
---
src/React.Core/IReactSiteConfiguration.cs | 20 +++---
src/React.Core/ReactSiteConfiguration.cs | 18 ++---
src/React.Sample.CoreMvc/Startup.cs | 16 ++---
tests/React.Tests/Core/ReactComponentTest.cs | 70 ++++++++++----------
4 files changed, 62 insertions(+), 62 deletions(-)
diff --git a/src/React.Core/IReactSiteConfiguration.cs b/src/React.Core/IReactSiteConfiguration.cs
index cb6e41dfb..50b742eae 100644
--- a/src/React.Core/IReactSiteConfiguration.cs
+++ b/src/React.Core/IReactSiteConfiguration.cs
@@ -178,20 +178,20 @@ public interface IReactSiteConfiguration
///
/// Disables server-side rendering. This is useful when debugging your scripts.
///
- IReactSiteConfiguration DisableServerSideRendering();
-
+ IReactSiteConfiguration DisableServerSideRendering();
+
///
/// An exception handler which will be called if a render exception is thrown.
/// If unset, unhandled exceptions will be thrown for all component renders.
///
- Action ExceptionHandler { get; set; }
-
- ///
- /// Sets an exception handler which will be called if a render exception is thrown.
- /// If unset, unhandled exceptions will be thrown for all component renders.
- ///
- ///
- ///
+ Action ExceptionHandler { get; set; }
+
+ ///
+ /// Sets an exception handler which will be called if a render exception is thrown.
+ /// If unset, unhandled exceptions will be thrown for all component renders.
+ ///
+ ///
+ ///
IReactSiteConfiguration SetExceptionHandler(Action handler);
}
}
diff --git a/src/React.Core/ReactSiteConfiguration.cs b/src/React.Core/ReactSiteConfiguration.cs
index ee1850610..c2e78dc49 100644
--- a/src/React.Core/ReactSiteConfiguration.cs
+++ b/src/React.Core/ReactSiteConfiguration.cs
@@ -7,10 +7,10 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
-using Newtonsoft.Json;
+using System;
using System.Collections.Generic;
using System.Linq;
-using System;
+using Newtonsoft.Json;
namespace React
{
@@ -306,13 +306,13 @@ public IReactSiteConfiguration DisableServerSideRendering()
/// Handle an exception caught during server-render of a component.
/// If unset, unhandled exceptions will be thrown for all component renders.
///
- public Action ExceptionHandler { get; set; }
-
- ///
- ///
- ///
- ///
- ///
+ public Action ExceptionHandler { get; set; }
+
+ ///
+ ///
+ ///
+ ///
+ ///
public IReactSiteConfiguration SetExceptionHandler(Action handler)
{
ExceptionHandler = handler;
diff --git a/src/React.Sample.CoreMvc/Startup.cs b/src/React.Sample.CoreMvc/Startup.cs
index fb70be38a..9dcf3bde5 100644
--- a/src/React.Sample.CoreMvc/Startup.cs
+++ b/src/React.Sample.CoreMvc/Startup.cs
@@ -21,14 +21,14 @@ namespace React.Sample.CoreMvc
public class Startup
{
public Startup(IHostingEnvironment env, ILogger logger)
- {
- // Setup configuration sources.
+ {
+ // Setup configuration sources.
var builder = new ConfigurationBuilder().AddEnvironmentVariables();
Logger = logger;
Configuration = builder.Build();
}
- public IConfiguration Configuration { get; set; }
+ public IConfiguration Configuration { get; set; }
public ILogger Logger { get; set; }
// This method gets called by the runtime.
@@ -70,12 +70,12 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
{
config
.SetReuseJavaScriptEngines(true)
- .AddScript("~/js/Sample.jsx")
- .SetExceptionHandler(ex =>
- {
- Logger.LogError("React component exception thrown!" + ex.ToString());
+ .AddScript("~/js/Sample.jsx")
+ .SetExceptionHandler(ex =>
+ {
+ Logger.LogError("React component exception thrown!" + ex.ToString());
})
- .SetUseDebugReact(true);
+ .SetUseDebugReact(true);
});
// Add static files to the request pipeline.
diff --git a/tests/React.Tests/Core/ReactComponentTest.cs b/tests/React.Tests/Core/ReactComponentTest.cs
index e61a9c012..be260d870 100644
--- a/tests/React.Tests/Core/ReactComponentTest.cs
+++ b/tests/React.Tests/Core/ReactComponentTest.cs
@@ -5,14 +5,14 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
-using System;
-using JavaScriptEngineSwitcher.Core;
+ */
+
+using System;
+using JavaScriptEngineSwitcher.Core;
using Moq;
using React.Exceptions;
using Xunit;
-
+
namespace React.Tests.Core
{
public class ReactComponentTest
@@ -162,7 +162,7 @@ public void RenderJavaScriptShouldCallRenderComponent()
);
}
- [Theory]
+ [Theory]
[InlineData("Foo", true)]
[InlineData("Foo.Bar", true)]
[InlineData("Foo.Bar.Baz", true)]
@@ -192,43 +192,43 @@ public void GeneratesContainerIdIfNotProvided()
var component = new ReactComponent(environment.Object, config.Object, "Foo", null);
Assert.StartsWith("react_", component.ContainerId);
- }
-
- [Fact]
- public void ExceptionThrownIsHandled()
- {
+ }
+
+ [Fact]
+ public void ExceptionThrownIsHandled()
+ {
var environment = new Mock();
environment.Setup(x => x.Execute("typeof Foo !== 'undefined'")).Returns(true);
environment.Setup(x => x.Execute(@"ReactDOMServer.renderToString(React.createElement(Foo, {""hello"":""World""}))"))
- .Throws(new JsRuntimeException("'undefined' is not an object"));
-
- var config = new Mock();
+ .Throws(new JsRuntimeException("'undefined' is not an object"));
+
+ var config = new Mock();
config.Setup(x => x.UseServerSideRendering).Returns(true);
var component = new ReactComponent(environment.Object, config.Object, "Foo", "container")
{
Props = new { hello = "World" }
- };
-
- // Default behavior
- bool exceptionCaught = false;
- try
- {
- component.RenderHtml();
- }
- catch (ReactServerRenderingException)
- {
- exceptionCaught = true;
- }
-
- Assert.True(exceptionCaught);
-
- // Custom exception handler set
- Exception caughtException = null;
- config.Setup(x => x.ExceptionHandler).Returns(ex => caughtException = ex);
-
- var result = component.RenderHtml();
- Assert.Equal(@"", result);
+ };
+
+ // Default behavior
+ bool exceptionCaught = false;
+ try
+ {
+ component.RenderHtml();
+ }
+ catch (ReactServerRenderingException)
+ {
+ exceptionCaught = true;
+ }
+
+ Assert.True(exceptionCaught);
+
+ // Custom exception handler set
+ Exception caughtException = null;
+ config.Setup(x => x.ExceptionHandler).Returns(ex => caughtException = ex);
+
+ var result = component.RenderHtml();
+ Assert.Equal(@"", result);
Assert.NotNull(caughtException);
}
}
From 46b45b3373f761cdf008828ae86978f61a8f4151 Mon Sep 17 00:00:00 2001
From: Dustin Masters
Date: Tue, 19 Dec 2017 07:55:40 -0800
Subject: [PATCH 4/5] Support component-level exception handlers
---
src/React.AspNet/HtmlHelperExtensions.cs | 11 +++++----
src/React.Core/IReactComponent.cs | 13 ++++++----
src/React.Core/IReactSiteConfiguration.cs | 4 ++--
src/React.Core/ReactComponent.cs | 24 +++++++++----------
src/React.Core/ReactSiteConfiguration.cs | 12 ++++++++--
src/React.Sample.CoreMvc/Startup.cs | 6 ++---
tests/React.Tests/Core/ReactComponentTest.cs | 13 +++++++---
.../Mvc/HtmlHelperExtensionsTests.cs | 20 ++++++++--------
8 files changed, 61 insertions(+), 42 deletions(-)
diff --git a/src/React.AspNet/HtmlHelperExtensions.cs b/src/React.AspNet/HtmlHelperExtensions.cs
index cb6b168c9..66e6a602c 100644
--- a/src/React.AspNet/HtmlHelperExtensions.cs
+++ b/src/React.AspNet/HtmlHelperExtensions.cs
@@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*/
+using System;
using React.Exceptions;
using React.TinyIoC;
@@ -64,7 +65,8 @@ public static IHtmlString React(
string containerId = null,
bool clientOnly = false,
bool serverOnly = false,
- string containerClass = null
+ string containerClass = null,
+ Action exceptionHandler = null
)
{
try
@@ -78,7 +80,7 @@ public static IHtmlString React(
{
reactComponent.ContainerClass = containerClass;
}
- var result = reactComponent.RenderHtml(clientOnly, serverOnly);
+ var result = reactComponent.RenderHtml(clientOnly, serverOnly, exceptionHandler);
return new HtmlString(result);
}
finally
@@ -108,7 +110,8 @@ public static IHtmlString ReactWithInit(
string htmlTag = null,
string containerId = null,
bool clientOnly = false,
- string containerClass = null
+ string containerClass = null,
+ Action exceptionHandler = null
)
{
try
@@ -122,7 +125,7 @@ public static IHtmlString ReactWithInit(
{
reactComponent.ContainerClass = containerClass;
}
- var html = reactComponent.RenderHtml(clientOnly);
+ var html = reactComponent.RenderHtml(clientOnly, exceptionHandler: exceptionHandler);
#if LEGACYASPNET
var script = new TagBuilder("script")
diff --git a/src/React.Core/IReactComponent.cs b/src/React.Core/IReactComponent.cs
index 04016d09a..48078a760 100644
--- a/src/React.Core/IReactComponent.cs
+++ b/src/React.Core/IReactComponent.cs
@@ -1,14 +1,16 @@
-/*
+/*
* Copyright (c) 2014-Present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
+ */
+
+using System;
namespace React
-{
+{
///
/// Represents a React JavaScript component.
///
@@ -44,9 +46,10 @@ public interface IReactComponent
/// return the rendered HTML.
///
/// Only renders component container. Used for client-side only rendering.
- /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
+ /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
+ ///
/// HTML
- string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false);
+ string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false, Action exceptionHandler = null);
///
/// Renders the JavaScript required to initialise this component client-side. This will
diff --git a/src/React.Core/IReactSiteConfiguration.cs b/src/React.Core/IReactSiteConfiguration.cs
index 50b742eae..8c3eed6da 100644
--- a/src/React.Core/IReactSiteConfiguration.cs
+++ b/src/React.Core/IReactSiteConfiguration.cs
@@ -184,7 +184,7 @@ public interface IReactSiteConfiguration
/// An exception handler which will be called if a render exception is thrown.
/// If unset, unhandled exceptions will be thrown for all component renders.
///
- Action ExceptionHandler { get; set; }
+ Action ExceptionHandler { get; set; }
///
/// Sets an exception handler which will be called if a render exception is thrown.
@@ -192,6 +192,6 @@ public interface IReactSiteConfiguration
///
///
///
- IReactSiteConfiguration SetExceptionHandler(Action handler);
+ IReactSiteConfiguration SetExceptionHandler(Action handler);
}
}
diff --git a/src/React.Core/ReactComponent.cs b/src/React.Core/ReactComponent.cs
index cf941ca3b..2ebe4a7b8 100644
--- a/src/React.Core/ReactComponent.cs
+++ b/src/React.Core/ReactComponent.cs
@@ -5,8 +5,8 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
+ */
+
using System;
using System.Linq;
using System.Text.RegularExpressions;
@@ -15,7 +15,7 @@
using React.Exceptions;
namespace React
-{
+{
///
/// Represents a React JavaScript component.
///
@@ -106,9 +106,10 @@ public ReactComponent(IReactEnvironment environment, IReactSiteConfiguration con
/// return the rendered HTML.
///
/// Only renders component container. Used for client-side only rendering.
- /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
+ /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
+ ///
/// HTML
- public virtual string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false)
+ public virtual string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false, Action exceptionHandler = null)
{
if (!_configuration.UseServerSideRendering)
{
@@ -132,15 +133,12 @@ public virtual string RenderHtml(bool renderContainerOnly = false, bool renderSe
}
catch (JsRuntimeException ex)
{
- if (_configuration.ExceptionHandler == null) {
- throw new ReactServerRenderingException(string.Format(
- "Error while rendering \"{0}\" to \"{2}\": {1}",
- ComponentName,
- ex.Message,
- ContainerId
- ));
+ if (exceptionHandler == null)
+ {
+ exceptionHandler = _configuration.ExceptionHandler;
}
- _configuration.ExceptionHandler(ex);
+
+ exceptionHandler(ex, ComponentName, ContainerId);
}
}
diff --git a/src/React.Core/ReactSiteConfiguration.cs b/src/React.Core/ReactSiteConfiguration.cs
index c2e78dc49..879a92db9 100644
--- a/src/React.Core/ReactSiteConfiguration.cs
+++ b/src/React.Core/ReactSiteConfiguration.cs
@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
+using React.Exceptions;
namespace React
{
@@ -45,6 +46,13 @@ public ReactSiteConfiguration()
};
UseDebugReact = false;
UseServerSideRendering = true;
+ ExceptionHandler = (Exception ex, string ComponentName, string ContainerId) =>
+ throw new ReactServerRenderingException(string.Format(
+ "Error while rendering \"{0}\" to \"{2}\": {1}",
+ ComponentName,
+ ex.Message,
+ ContainerId
+ ));
}
///
@@ -306,14 +314,14 @@ public IReactSiteConfiguration DisableServerSideRendering()
/// Handle an exception caught during server-render of a component.
/// If unset, unhandled exceptions will be thrown for all component renders.
///
- public Action ExceptionHandler { get; set; }
+ public Action ExceptionHandler { get; set; }
///
///
///
///
///
- public IReactSiteConfiguration SetExceptionHandler(Action handler)
+ public IReactSiteConfiguration SetExceptionHandler(Action handler)
{
ExceptionHandler = handler;
return this;
diff --git a/src/React.Sample.CoreMvc/Startup.cs b/src/React.Sample.CoreMvc/Startup.cs
index 9dcf3bde5..d4b0da082 100644
--- a/src/React.Sample.CoreMvc/Startup.cs
+++ b/src/React.Sample.CoreMvc/Startup.cs
@@ -5,8 +5,8 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
+ */
+
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
@@ -71,7 +71,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
config
.SetReuseJavaScriptEngines(true)
.AddScript("~/js/Sample.jsx")
- .SetExceptionHandler(ex =>
+ .SetExceptionHandler((ex, name, id) =>
{
Logger.LogError("React component exception thrown!" + ex.ToString());
})
diff --git a/tests/React.Tests/Core/ReactComponentTest.cs b/tests/React.Tests/Core/ReactComponentTest.cs
index be260d870..234825b05 100644
--- a/tests/React.Tests/Core/ReactComponentTest.cs
+++ b/tests/React.Tests/Core/ReactComponentTest.cs
@@ -5,8 +5,8 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
+ */
+
using System;
using JavaScriptEngineSwitcher.Core;
using Moq;
@@ -204,6 +204,7 @@ public void ExceptionThrownIsHandled()
var config = new Mock();
config.Setup(x => x.UseServerSideRendering).Returns(true);
+ config.Setup(x => x.ExceptionHandler).Returns(() => throw new ReactServerRenderingException("test"));
var component = new ReactComponent(environment.Object, config.Object, "Foo", "container")
{
@@ -223,9 +224,15 @@ public void ExceptionThrownIsHandled()
Assert.True(exceptionCaught);
+ // Custom handler passed into render call
+ bool customHandlerInvoked = false;
+ Action customHandler = (ex, name, id) => customHandlerInvoked = true;
+ component.RenderHtml(exceptionHandler: customHandler);
+ Assert.True(customHandlerInvoked);
+
// Custom exception handler set
Exception caughtException = null;
- config.Setup(x => x.ExceptionHandler).Returns(ex => caughtException = ex);
+ config.Setup(x => x.ExceptionHandler).Returns((ex, name, id) => caughtException = ex);
var result = component.RenderHtml();
Assert.Equal(@"", result);
diff --git a/tests/React.Tests/Mvc/HtmlHelperExtensionsTests.cs b/tests/React.Tests/Mvc/HtmlHelperExtensionsTests.cs
index f087fdd77..14d1253a4 100644
--- a/tests/React.Tests/Mvc/HtmlHelperExtensionsTests.cs
+++ b/tests/React.Tests/Mvc/HtmlHelperExtensionsTests.cs
@@ -5,11 +5,11 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
+ */
+
using Moq;
-using Xunit;
using React.Web.Mvc;
+using Xunit;
namespace React.Tests.Mvc
{
@@ -31,7 +31,7 @@ private Mock ConfigureMockEnvironment()
public void ReactWithInitShouldReturnHtmlAndScript()
{
var component = new Mock();
- component.Setup(x => x.RenderHtml(false, false)).Returns("HTML");
+ component.Setup(x => x.RenderHtml(false, false, null)).Returns("HTML");
component.Setup(x => x.RenderJavaScript()).Returns("JS");
var environment = ConfigureMockEnvironment();
environment.Setup(x => x.CreateComponent(
@@ -57,7 +57,7 @@ public void ReactWithInitShouldReturnHtmlAndScript()
public void EngineIsReturnedToPoolAfterRender()
{
var component = new Mock();
- component.Setup(x => x.RenderHtml(true, true)).Returns("HTML");
+ component.Setup(x => x.RenderHtml(true, true, null)).Returns("HTML");
var environment = ConfigureMockEnvironment();
environment.Setup(x => x.CreateComponent(
"ComponentName",
@@ -75,7 +75,7 @@ public void EngineIsReturnedToPoolAfterRender()
clientOnly: true,
serverOnly: true
);
- component.Verify(x => x.RenderHtml(It.Is(y => y == true), It.Is(z => z == true)), Times.Once);
+ component.Verify(x => x.RenderHtml(It.Is(y => y == true), It.Is(z => z == true), null), Times.Once);
environment.Verify(x => x.ReturnEngineToPool(), Times.Once);
}
@@ -83,7 +83,7 @@ public void EngineIsReturnedToPoolAfterRender()
public void ReactWithClientOnlyTrueShouldCallRenderHtmlWithTrue()
{
var component = new Mock();
- component.Setup(x => x.RenderHtml(true, true)).Returns("HTML");
+ component.Setup(x => x.RenderHtml(true, true, null)).Returns("HTML");
var environment = ConfigureMockEnvironment();
environment.Setup(x => x.CreateComponent(
"ComponentName",
@@ -100,13 +100,13 @@ public void ReactWithClientOnlyTrueShouldCallRenderHtmlWithTrue()
clientOnly: true,
serverOnly: true
);
- component.Verify(x => x.RenderHtml(It.Is(y => y == true), It.Is(z => z == true)), Times.Once);
+ component.Verify(x => x.RenderHtml(It.Is(y => y == true), It.Is(z => z == true), null), Times.Once);
}
[Fact]
public void ReactWithServerOnlyTrueShouldCallRenderHtmlWithTrue() {
var component = new Mock();
- component.Setup(x => x.RenderHtml(true, true)).Returns("HTML");
+ component.Setup(x => x.RenderHtml(true, true, null)).Returns("HTML");
var environment = ConfigureMockEnvironment();
environment.Setup(x => x.CreateComponent(
"ComponentName",
@@ -123,7 +123,7 @@ public void ReactWithServerOnlyTrueShouldCallRenderHtmlWithTrue() {
clientOnly: true,
serverOnly: true
);
- component.Verify(x => x.RenderHtml(It.Is(y => y == true), It.Is(z => z == true)), Times.Once);
+ component.Verify(x => x.RenderHtml(It.Is(y => y == true), It.Is(z => z == true), null), Times.Once);
}
}
}
From 13c99266fca73bf5c1dc9d594aa6a76b4c125bd1 Mon Sep 17 00:00:00 2001
From: Dustin Masters
Date: Tue, 19 Dec 2017 07:58:50 -0800
Subject: [PATCH 5/5] Document exceptionHandler arguments
---
src/React.AspNet/HtmlHelperExtensions.cs | 2 ++
src/React.Core/IReactComponent.cs | 10 +++++-----
src/React.Core/ReactComponent.cs | 10 +++++-----
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/src/React.AspNet/HtmlHelperExtensions.cs b/src/React.AspNet/HtmlHelperExtensions.cs
index 66e6a602c..b136ca42f 100644
--- a/src/React.AspNet/HtmlHelperExtensions.cs
+++ b/src/React.AspNet/HtmlHelperExtensions.cs
@@ -56,6 +56,7 @@ private static IReactEnvironment Environment
/// Skip rendering server-side and only output client-side initialisation code. Defaults to false
/// Skip rendering React specific data-attributes during server side rendering. Defaults to false
/// HTML class(es) to set on the container tag
+ /// A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)
/// The component's HTML
public static IHtmlString React(
this IHtmlHelper htmlHelper,
@@ -102,6 +103,7 @@ public static IHtmlString React(
/// ID to use for the container HTML tag. Defaults to an auto-generated ID
/// Skip rendering server-side and only output client-side initialisation code. Defaults to false
/// HTML class(es) to set on the container tag
+ /// A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)
/// The component's HTML
public static IHtmlString ReactWithInit(
this IHtmlHelper htmlHelper,
diff --git a/src/React.Core/IReactComponent.cs b/src/React.Core/IReactComponent.cs
index 48078a760..3cdf7f794 100644
--- a/src/React.Core/IReactComponent.cs
+++ b/src/React.Core/IReactComponent.cs
@@ -5,12 +5,12 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
+ */
+
using System;
namespace React
-{
+{
///
/// Represents a React JavaScript component.
///
@@ -46,8 +46,8 @@ public interface IReactComponent
/// return the rendered HTML.
///
/// Only renders component container. Used for client-side only rendering.
- /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
- ///
+ /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
+ /// A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)
/// HTML
string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false, Action exceptionHandler = null);
diff --git a/src/React.Core/ReactComponent.cs b/src/React.Core/ReactComponent.cs
index 2ebe4a7b8..e736604f0 100644
--- a/src/React.Core/ReactComponent.cs
+++ b/src/React.Core/ReactComponent.cs
@@ -5,8 +5,8 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
- */
-
+ */
+
using System;
using System.Linq;
using System.Text.RegularExpressions;
@@ -15,7 +15,7 @@
using React.Exceptions;
namespace React
-{
+{
///
/// Represents a React JavaScript component.
///
@@ -106,8 +106,8 @@ public ReactComponent(IReactEnvironment environment, IReactSiteConfiguration con
/// return the rendered HTML.
///
/// Only renders component container. Used for client-side only rendering.
- /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
- ///
+ /// Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.
+ /// A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)
/// HTML
public virtual string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false, Action exceptionHandler = null)
{