Ejemplo n.º 1
0
        /// <summary>
        /// Render a React StaticRouter Component with context object.
        /// Can optionally be provided with a custom context handler to handle the various status codes.
        /// </summary>
        /// <param name="htmlHelper">MVC Razor <see cref="IHtmlHelper"/></param>
        /// <param name="componentName">Name of React Static Router component. Expose component globally to ReactJS.NET</param>
        /// <param name="props">Props to initialise the component with</param>
        /// <param name="path">F.x. from Request.Path. Used by React Static Router to determine context and routing.</param>
        /// <param name="contextHandler">Optional custom context handler, can be used instead of providing a Response object</param>
        /// <param name="htmlTag">HTML tag to wrap the component in. Defaults to &lt;div&gt;</param>
        /// <param name="containerId">ID to use for the container HTML tag. Defaults to an auto-generated ID</param>
        /// <param name="clientOnly">Skip rendering server-side and only output client-side initialisation code. Defaults to <c>false</c></param>
        /// <param name="serverOnly">Skip rendering React specific data-attributes during server side rendering. Defaults to <c>false</c></param>
        /// <param name="containerClass">HTML class(es) to set on the container tag</param>
        /// <param name="renderFunctions">Functions to call during component render</param>
        /// <returns><see cref="IHtmlString"/> containing the rendered markup for provided React Router component</returns>
        public static IHtmlString ReactRouter <T>(
            this IHtmlHelper htmlHelper,
            string componentName,
            T props,
            string path           = null,
            string htmlTag        = null,
            string containerId    = null,
            bool clientOnly       = false,
            bool serverOnly       = false,
            string containerClass = null,
            Action <HttpResponse, RoutingContext> contextHandler = null,
            IRenderFunctions renderFunctions = null
            )
        {
            try
            {
                var response = htmlHelper.ViewContext.HttpContext.Response;
                path = path ?? htmlHelper.ViewContext.HttpContext.Request.Path;

                var reactComponent
                    = Environment.CreateRouterComponent(
                          componentName,
                          props,
                          path,
                          containerId,
                          clientOnly
                          );

                if (!string.IsNullOrEmpty(htmlTag))
                {
                    reactComponent.ContainerTag = htmlTag;
                }
                if (!string.IsNullOrEmpty(containerClass))
                {
                    reactComponent.ContainerClass = containerClass;
                }

                var executionResult = reactComponent.RenderRouterWithContext(clientOnly, serverOnly, renderFunctions);

                if (executionResult.Context?.status != null || executionResult.Context?.url != null)
                {
                    // Use provided contextHandler
                    if (contextHandler != null)
                    {
                        contextHandler(response, executionResult.Context);
                    }
                    // Handle routing context internally
                    else
                    {
                        SetServerResponse.ModifyResponse(executionResult.Context, response);
                    }
                }

                return(new HtmlString(executionResult.RenderResult));
            }
            finally
            {
                Environment.ReturnEngineToPool();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Renders the specified React component
        /// </summary>
        /// <typeparam name="T">Type of the props</typeparam>
        /// <param name="htmlHelper">HTML helper</param>
        /// <param name="componentName">Name of the component</param>
        /// <param name="props">Props to initialise the component with</param>
        /// <param name="htmlTag">HTML tag to wrap the component in. Defaults to &lt;div&gt;</param>
        /// <param name="containerId">ID to use for the container HTML tag. Defaults to an auto-generated ID</param>
        /// <param name="clientOnly">Skip rendering server-side and only output client-side initialisation code. Defaults to <c>false</c></param>
        /// <param name="serverOnly">Skip rendering React specific data-attributes, container and client-side initialisation during server side rendering. Defaults to <c>false</c></param>
        /// <param name="containerClass">HTML class(es) to set on the container tag</param>
        /// <param name="exceptionHandler">A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)</param>
        /// <param name="renderFunctions">Functions to call during component render</param>
        /// <returns>The component's HTML</returns>
        public static IHtmlString React <T>(
            this IHtmlHelper htmlHelper,
            string componentName,
            T props,
            string htmlTag        = null,
            string containerId    = null,
            bool clientOnly       = false,
            bool serverOnly       = false,
            string containerClass = null,
            Action <Exception, string, string> exceptionHandler = null,
            IRenderFunctions renderFunctions = null
            )
        {
            try
            {
                var reactComponent = Environment.CreateComponent(componentName, props, containerId, clientOnly, serverOnly);
                if (!string.IsNullOrEmpty(htmlTag))
                {
                    reactComponent.ContainerTag = htmlTag;
                }

                if (!string.IsNullOrEmpty(containerClass))
                {
                    reactComponent.ContainerClass = containerClass;
                }

                return(RenderToString(writer => reactComponent.RenderHtml(writer, clientOnly, serverOnly, exceptionHandler, renderFunctions)));
            }
            finally
            {
                Environment.ReturnEngineToPool();
            }
        }
        /// <summary>
        /// Render a React StaticRouter Component with context object.
        /// </summary>
        /// <param name="renderContainerOnly">Only renders component container. Used for client-side only rendering. Does not make sense in this context but included for consistency</param>
        /// <param name="renderServerOnly">Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.</param>
        /// <param name="renderFunctions">Functions to call during component render</param>
        /// <returns>Object containing HTML in string format and the React Router context object</returns>
        public virtual ExecutionResult RenderRouterWithContext(
            bool renderContainerOnly         = false,
            bool renderServerOnly            = false,
            IRenderFunctions renderFunctions = null
            )
        {
            var reactRouterFunctions = new ReactRouterFunctions(renderFunctions: renderFunctions);

            var html = RenderHtml(
                renderContainerOnly,
                renderServerOnly,
                renderFunctions: reactRouterFunctions
                );

            return(new ExecutionResult
            {
                RenderResult = html,
                Context = JsonConvert.DeserializeObject <RoutingContext>(reactRouterFunctions.ReactRouterContext),
            });
        }
 /// <summary>
 /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next.
 /// The functions within the provided RenderFunctions will be called *after* this instance's.
 /// Supports null as an argument.
 /// </summary>
 /// <param name="renderFunctions">The chained render functions to call</param>
 public EmotionFunctions(IRenderFunctions renderFunctions = null)
     : base(renderFunctions)
 {
 }
Ejemplo n.º 5
0
 public TestRenderFunctions(IRenderFunctions renderFunctions = null)
     : base(renderFunctions)
 {
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Renders the HTML for this component. This will execute the component server-side and
        /// return the rendered HTML.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.IO.TextWriter" /> to which the content is written</param>
        /// <param name="renderContainerOnly">Only renders component container. Used for client-side only rendering.</param>
        /// <param name="renderServerOnly">Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.</param>
        /// <param name="exceptionHandler">A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)</param>
        /// <param name="renderFunctions">Functions to call during component render</param>
        /// <returns>HTML</returns>
        public virtual void RenderHtml(TextWriter writer, bool renderContainerOnly = false, bool renderServerOnly = false, Action <Exception, string, string> exceptionHandler = null, IRenderFunctions renderFunctions = null)
        {
            if (!_configuration.UseServerSideRendering)
            {
                renderContainerOnly = true;
            }

            if (!renderContainerOnly)
            {
                EnsureComponentExists();
            }

            var html = string.Empty;

            if (!renderContainerOnly)
            {
                var stringWriter = _sharedStringWriter;
                if (stringWriter != null)
                {
                    stringWriter.GetStringBuilder().Clear();
                }
                else
                {
                    _sharedStringWriter = stringWriter = new StringWriter(new StringBuilder(_serializedProps.Length + 128));
                }

                try
                {
                    stringWriter.Write(renderServerOnly ? "ReactDOMServer.renderToStaticMarkup(" : "ReactDOMServer.renderToString(");
                    if (renderFunctions != null)
                    {
                        stringWriter.Write(renderFunctions.WrapComponent(GetStringFromWriter(componentInitWriter => WriteComponentInitialiser(componentInitWriter))));
                    }
                    else
                    {
                        WriteComponentInitialiser(stringWriter);
                    }
                    stringWriter.Write(')');

                    if (renderFunctions != null)
                    {
                        renderFunctions.PreRender(x => _environment.Execute <string>(x));
                        html = _environment.Execute <string>(renderFunctions.TransformRenderedHtml(stringWriter.ToString()));
                        renderFunctions.PostRender(x => _environment.Execute <string>(x));
                    }
                    else
                    {
                        html = _environment.Execute <string>(stringWriter.ToString());
                    }

                    if (renderServerOnly)
                    {
                        writer.Write(html);
                        return;
                    }
                }
                catch (JsException ex)
                {
                    if (exceptionHandler == null)
                    {
                        exceptionHandler = _configuration.ExceptionHandler;
                    }

                    exceptionHandler(ex, ComponentName, ContainerId);
                }
            }

            writer.Write('<');
            writer.Write(ContainerTag);
            writer.Write(" id=\"");
            writer.Write(ContainerId);
            writer.Write('"');
            if (!string.IsNullOrEmpty(ContainerClass))
            {
                writer.Write(" class=\"");
                writer.Write(ContainerClass);
                writer.Write('"');
            }

            writer.Write('>');
            writer.Write(html);
            writer.Write("</");
            writer.Write(ContainerTag);
            writer.Write('>');
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Renders the HTML for this component. This will execute the component server-side and
 /// return the rendered HTML.
 /// </summary>
 /// <param name="renderContainerOnly">Only renders component container. Used for client-side only rendering.</param>
 /// <param name="renderServerOnly">Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.</param>
 /// <param name="exceptionHandler">A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)</param>
 /// <param name="renderFunctions">Functions to call during component render</param>
 /// <returns>HTML</returns>
 public virtual string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false, Action <Exception, string, string> exceptionHandler = null, IRenderFunctions renderFunctions = null)
 {
     return(GetStringFromWriter(renderHtmlWriter => RenderHtml(renderHtmlWriter, renderContainerOnly, renderServerOnly, exceptionHandler, renderFunctions)));
 }
 /// <summary>
 /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next.
 /// The functions within the provided RenderFunctions will be called *after* this instance's.
 /// Supports null as an argument.
 /// </summary>
 /// <param name="renderFunctions">The chained render functions to call</param>
 public ReactJssFunctions(IRenderFunctions renderFunctions = null)
     : base(renderFunctions)
 {
 }
 /// <summary>
 /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next.
 /// The functions within the provided RenderFunctions will be called *after* this instance's.
 /// Supports null as an argument.
 /// </summary>
 /// <param name="renderFunctions">The chained render functions to call</param>
 public ReactHelmetFunctions(IRenderFunctions renderFunctions = null)
     : base(renderFunctions)
 {
 }
 /// <summary>
 /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next.
 /// The functions within the provided RenderFunctions will be called *after* this instance's.
 /// Supports null as an argument.
 /// </summary>
 /// <param name="renderFunctions">The chained render functions to call</param>
 public StyledComponentsFunctions(IRenderFunctions renderFunctions = null)
     : base(renderFunctions)
 {
 }
Ejemplo n.º 11
0
        public static IHtmlString ReactWithModel <T>(this HtmlHelper htmlHelper, string componentName, T props, string htmlTag = null, string containerId = null, bool clientOnly = false, bool serverOnly = false, string containerClass = null, Action <Exception, string, string> exceptionHandler = null, IRenderFunctions renderFunctions = null)
        {
            try
            {
                var sb = new StringBuilder();
                containerId = componentName.ToLower();

                IReactComponent component = Environment.CreateComponent <T>(componentName, props, containerId, clientOnly, serverOnly);
                if (!string.IsNullOrEmpty(htmlTag))
                {
                    component.ContainerTag = htmlTag;
                }
                if (!string.IsNullOrEmpty(containerClass))
                {
                    component.ContainerClass = containerClass;
                }

                var originalResult  = component.RenderHtml(clientOnly, serverOnly);
                var serializedModel = JsonConvert.SerializeObject(props);

                sb.Append($"<div data-react-component=\"{componentName.ToLower()}\">");
                sb.Append(originalResult);
                sb.Append($"<script>");
                sb.Append($"{serializedModel}");
                sb.Append("</script>");
                sb.Append("</div>");

                return(new HtmlString(sb.ToString()));
            }
            finally
            {
                Environment.ReturnEngineToPool();
            }
        }
 /// <summary>
 /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next.
 /// The functions within the provided RenderFunctions will be called *after* this instance's.
 /// Supports null as an argument.
 /// </summary>
 /// <param name="renderFunctions">The chained render functions to call</param>
 protected RenderFunctionsBase(IRenderFunctions renderFunctions)
 {
     _renderFunctions = renderFunctions;
 }