asp.net - tag - Depuración de representación del servidor Aspnet
servidor web asp (3)
He hecho algunas investigaciones y he llegado a la conclusión de que no es posible, por el momento, depurar el código del servidor inicial.
Lo que he hecho en su lugar es implementar la lógica, para poder desactivar el procesamiento del servidor.
Así es como esto luce:
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>
}
boot-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
});
}
boot-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"
}
así que ahora puedo simplemente cambiar la representación del servidor agregando un? server = false al final de la url y comenzar a depurar :)
Tengo una aplicación react-redux que se ejecuta en el núcleo de aspnet, con representación del lado del servidor mediante el preentrenamiento de aspnet.
Digamos que hago un error de programación, donde en el componente secundario trato de acceder a un puntero indefinido debido a un estúpido error tipográfico.
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
}
Sin la representación del servidor, habría obtenido un error similar al siguiente: no puedo acceder a algo indefinido en la línea x: yy Pero con la ejecución del servidor obtengo un:
Se produjo una excepción no controlada al procesar la solicitud.
Excepción: el módulo de llamada al nodo ha fallado con el error: el tiempo de espera de la ejecución se ha agotado después de 30000 ms porque la función de arranque en ''ClientApp / src / boot-server'' devolvió una promesa que no se resolvió o rechazó. Asegúrese de que su función de arranque siempre resuelve o rechaza su promesa. Puede cambiar el valor de tiempo de espera utilizando el asistente de etiquetas ''asp-prerender-timeout''.
esto hace que la depuración sea bastante difícil, cuando no recibes ningún comentario sobre lo que salió mal. ¿Alguien sabe cómo configurar un rechazo si algo falla? o incluso es posible depurar un código renderizado del lado del servidor?
aquí está mi archivo de servidor de arranque, dime si necesitas más archivos.
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
});
}
Encontré una solución que me funciona: inserté un try / catch en el renderToString final. donde en catch envío un despacho con el error.
boot-server.jsx actualizado
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
});
He tenido una experiencia similar trabajando con Visual Studio 2017. Eventualmente me di cuenta de que la información de diagnóstico para los errores originales estaba realmente en la ventana de Salida.