Отладка рендеринга сервера Aspnet

У меня есть приложение act-redux, работающее на ядре aspnet, с рендерингом на стороне сервера с использованием предварительного рендеринга aspnet

Допустим, я делаю ошибку в программировании, где в дочернем компоненте я пытаюсь получить доступ к неопределенной пропе из-за глупой опечатки.

import {Child} from './child'
export class Parent extends React.Component {
  render () {
    const someProp = {
      something: "something"
    };
    return <Child someProp={someProp} />;
  }
}

export class Child extends React.Component {
  render() {
    return <div>this.props.someprop.something</div>;
         //typo: should be someProp instead of someprop
}

Без рендеринга сервера я получил бы ошибку, похожую на эту: я не могу получить доступ к чему-то неопределенному в строке x:yy Но при рендеринге сервера я получаю:

Произошло необработанное исключение при обработке запроса.

Исключение: модуль Call to Node завершился неудачно с ошибкой: Превышение тайм-аута после 30000 мс, потому что функция загрузки в 'ClientApp/src/boot-server' возвратила обещание, которое не удалось разрешить или отклонить. Убедитесь, что ваша загрузочная функция всегда разрешает или отклоняет свое обещание. Вы можете изменить значение тайм-аута с помощью помощника по тегу asp-prerender-timeout.

это делает отладку довольно сложной, когда вы не получаете никакой обратной связи о том, что пошло не так. Кто-нибудь знает, как настроить отклонение, если что-то не получается? или это вообще возможно для отладки кода на стороне сервера?

вот мой файл загрузочного сервера, скажите мне, если вам нужны еще файлы.

import * as React from 'react';
import { Provider } from 'react-redux';
import { renderToString } from 'react-dom/server';
import configureStore from './store/configureStore';
import {getFormById} from './actions/getFormActions';
import {updateUserLocale} from './actions/userLocaleActions';
import FormResponder from './components/mainComponents/formResponder';

export default function renderApp (params) {

    return new Promise((resolve, reject) => {

        const store = configureStore();
        store.dispatch(getFormById(params.data.id, params.data.config, params.data.authenticationToken));
        store.dispatch(updateUserLocale(params.data.userLocale));
        const app = (
            <Provider store={ store }>
                <FormResponder />
            </Provider>
        );

    // Perform an initial render that will cause any async tasks (e.g., data access) to begin
    renderToString(app);

    // Once the tasks are done, we can perform the final render
    // We also send the redux store state, so the client can continue execution where the server left off
    params.domainTasks.then(() => {
        resolve({
            html: renderToString(app),
            globals: {
                initialReduxState: store.getState(), 
                authenticationToken: params.data.authenticationToken, 
                config: params.data.config
            }
        });
    }, reject); // Also propagate any errors back into the host application
});
}

3 ответа

Решение

Нашел решение, которое работает для меня: я вставил try/catch в final renderToString. Куда в улове я отправляю отправку с ошибкой.

обновлен boot-server.jsx

params.domainTasks.then(() => {
        let html;
        try {
            html = renderToString(app);
        }
        catch (err) {
            store.dispatch(loadFormFailed( {message: err.toString() } ));
        }

        resolve({
            html: html,
            globals: {
                initialReduxState: store.getState(), 
                authenticationToken: params.data.authenticationToken, 
                config: params.data.config,
                disableReactServerRendring: false
            }
        });
        }, reject);
        // Also propagate any errors back into the host application
    });

У меня был похожий опыт работы с Visual Studio 2017. В конце концов я понял, что диагностическая информация для исходных ошибок была на самом деле в окне вывода.

Я провел сом-исследование и пришел к выводу, что пока невозможно отладить исходный код сервера.

вместо этого я реализовал логику, чтобы отключить рендеринг сервера.

Вот как это выглядит:

public async Task<IActionResult> Index(string id, string userLocale = "en", bool server = true)
{ 
    Guid positionId;
    if (!Guid.TryParse(id, out positionId))
    {
        throw new Exception("Invalid position id");        
    }

    var token = await _apiClient.GetToken();

    var formData = new ApplicationFormViewModel()
    {
        Id = positionId,
        UserLocale = userLocale,
        AuthenticationToken = token.AccessToken,
        Server = server
    };
    return View(formData);
}

view.cshtml:

@{if (@Model.Server) {
    <div 
    class="container"
    id="react-app"
    asp-prerender-module="ClientApp/src/boot-server"
    asp-prerender-data="new {
        Id = @Model.Id, 
        UserLocale = @Model.UserLocale, 
        AuthenticationToken = @Model.AuthenticationToken, 
        Config = new { 
            ApplicationPostUrl = @Url.Action("SaveApplication"),
            AttachmentPostUrl = @Url.Action("UploadAttachment"),
            FormGetUrl = @Url.Action("GetForm")
        }
     }" 
     asp-prerender-webpack-config="webpack.config.js" >
        Loading...
</div>
}
else {
    <script>
        var id= '@Model.Id'; 
        var config= {
            applicationPostUrl: '@Url.Action("SaveApplication")',
            attachmentPostUrl: '@Url.Action("UploadAttachment")',
            formGetUrl: '@Url.Action("GetForm")'
        };
        var userLocale='@Model.UserLocale'; 
        var authenticationToken='@Model.AuthenticationToken'; 
        var server = false;
    </script>
    <div class="container" id="react-app">loading</div>

}
}



@section scripts {

    <script src="~/dist/main.js" asp-append-version="true"></script>
}

загрузки server.jsx:

export default function renderApp (params) {

    return new Promise((resolve, reject) => {

        const store = configureStore();
        store.dispatch(getFormById(params.data.id, params.data.config, params.data.authenticationToken));
        store.dispatch(updateUserLocale(params.data.userLocale));
        const app = (
            <Provider store={ store }>
                <FormResponder />
            </Provider>
        );

    // Perform an initial render that will cause any async tasks (e.g., data access) to begin
    renderToString(app);

    // Once the tasks are done, we can perform the final render
    // We also send the redux store state, so the client can continue execution where the server left off
    params.domainTasks.then(() => {
        resolve({
            html: renderToString(app),
            globals: {
                initialReduxState: store.getState(), 
                authenticationToken: params.data.authenticationToken, 
                config: params.data.config,
                server: true
            }
        });
        }, reject); // Also propagate any errors back into the host application
});
}

загрузки client.jsx:

// Grab the state from a global injected into server-generated HTML
const {id, initialReduxState, authenticationToken, config, server, userLocale } = window;

if (server) {


// Get the application-wide store instance, prepopulating with state from the server where available.
const store = configureStore(initialReduxState);
// This code starts up the React app when it runs in a browser.
ReactDOM.render(
    <Provider store={ store }>
        <FormResponder authenticationToken={authenticationToken} config={config} />
    </Provider>,
    document.getElementById('react-app')
);


}
else {

    const store = configureStore();
    store.dispatch(getFormById(id, config, authenticationToken));
    store.dispatch(updateUserLocale(userLocale));

    render(
        <Provider store ={store}>
            <FormResponder authenticationToken={authenticationToken} config={config} />
        </Provider>,
        document.getElementById('react-app')
    ); // Take our FormBuilder component and attach it with DOM element "app"
}

так что теперь я могу просто повернуть рендеринг сервера, добавив?server=false в конце URL, и начать отладку:)

Другие вопросы по тегам