.NET: ¿Qué excepción lanzar cuando falta una configuración de configuración requerida?


123

Aquí hay un escenario estándar:

if(string.IsNullOrEmpty(Configuration.AppSettings["foobar"]))
   throw new SomeStandardException("Application not configured correctly, bozo.");

El problema es que no estoy completamente seguro de qué excepción SomeStandardExceptiondebería ser.

Leí detenidamente el Marco 3.5 y encontré dos posibles candidatos: ConfigurationExceptiony ConfigurationErrorsException.

System.Configuration.ConfigurationException

La excepción que se produce cuando se produce un error del sistema de configuración.

Observaciones

La ConfigurationExceptionexcepción se produce si la aplicación intenta leer o escribir datos en el archivo de configuración pero no tiene éxito. Algunas posibles razones para esto pueden incluir XML con formato incorrecto en el archivo de configuración, problemas de permisos de archivo y propiedades de configuración con valores que no son válidos.

Nota:

El ConfigurationExceptionobjeto se mantiene por compatibilidad con versiones anteriores. El ConfigurationErrorsException objeto lo reemplaza por el sistema de configuración.

Esta excepción en realidad suena perfecta para lo que necesito, pero se ha marcado como obsoleta, por lo tanto, ixnay en atthay.

Esto nos lleva a lo completamente desconcertante ConfigurationErrorsException:

System.Configuration.ConfigurationErrorsException

El valor actual no es uno de los valores de EnableSessionState.

Como puede ver, su documentación es completamente inútil. (Es así en la ayuda local y en línea.) Un examen de la clase en sí muestra que es una exageración drástica de lo que quiero.

En pocas palabras, necesito una excepción estándar que se debe lanzar cuando falta una configuración de la aplicación o contiene un valor no válido. Se podría pensar que el Framework tenía una excepción incorporada para que las aplicaciones lo usaran. (Aparentemente lo hizo, pero se marcó como obsoleto y fue reemplazado por algo mucho más amplio).

¿Qué soluciones, si hay alguna, están usando para esto? ¿Tendré que aguantar y rodar mi propia excepción para esto?

Editar apéndices

Algunos han preguntado si puedo proporcionar un valor predeterminado o no y continuar. En ciertos casos, sí, y en esos casos, no se lanzaría la excepción. Sin embargo, para ciertas configuraciones, esto no se aplicará. Por ejemplo: nombres y credenciales de servidores de bases de datos, servidores de autenticación y rutas a aplicaciones de terceros instaladas.

También vale la pena señalar que la aplicación en la que estoy trabajando principalmente es una aplicación de consola que se ejecuta en modo por lotes, y quiero que arroje una excepción que sea atrapada por el método principal y se registre adecuadamente si la cosa no está configurada adecuadamente. (Es un código heredado que heredé, y actualmente solo asume que todo es color de rosa).


1
La documentación para System.Configuration.ConfigurationErrorsException ha sido actualizada.
slolife

Respuestas:


36

No está limitado en su lanzamiento de excepciones a las excepciones existentes en el Marco. Si decide usar excepciones existentes, no tiene que seguir la documentación al pie de la letra. La documentación describirá cómo el marco utiliza una excepción que se da, pero no implica ninguna limitación sobre la forma que elija para su uso / reutilización una excepción existente.

Es su aplicación: siempre que la documente e indique claramente la excepción que se lanzará en el caso específico de un valor de configuración faltante, puede usar cualquier excepción que desee. Si desea una indicación muy específica de un valor faltante , puede considerar escribir su propia excepción ConfigurationSettingMissing:

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

EDITAR: Escribir su propia excepción en este caso conlleva el beneficio adicional de garantizar que nunca habrá ninguna confusión sobre el origen de la excepción: el marco o su aplicación. El marco nunca arrojará sus excepciones personalizadas.

ACTUALIZACIÓN: estoy de acuerdo con los comentarios, por lo que he cambiado la subclase a Excepción de configuración de excepción de excepción. Creo que generalmente es una buena idea subclasificar las excepciones personalizadas de las excepciones existentes de Framework cuando sea posible, evitando la clase Exception a menos que necesite una excepción específica de la aplicación.


17
Estoy en desacuerdo un poco. Si va a usar una excepción existente, debe usarse EXACTAMENTE ya que la documentación dice que se usa, o de lo contrario confundirá a los que vienen después de usted. Si vas a hacer algo diferente, solo crea tu propia excepción, como dijiste.
Robert C. Barth

1
Estoy en desacuerdo. A menos que tenga un escenario para atrapar su excepción personalizada, poco probable en el caso de un error de configuración, es mejor reutilizar un Tipo existente (ConfigurationErrorsException). Y si crea un tipo personalizado, lo derivaría de un tipo relacionado, como ConfigurationErrorsException.
Joe

@Robert & Joe: no estoy sugiriendo que las excepciones existentes de Framework se usen de manera inconsistente con su función prevista, solo que hay cierta flexibilidad siempre que el caso específico (valor perdido) se ajuste al caso general (ConfigurationErrorsException).
Dave Swersky el

1
Podría haber problemas con esto si está lanzando la excepción dentro de una aplicación ASP.NET ya que ConfigurationErrorsException y las clases derivadas de ella no quedan atrapadas en el método OnError protegido o por el evento Global ASAX Error. Vea esta pregunta que he publicado ... stackoverflow.com/questions/25299325/…
Mick

48

Personalmente, usaría InvalidOperationException , ya que es un problema con el estado del objeto, no con el sistema de configuración. Después de todo, ¿no debería permitir que esta configuración se establezca por código y no por configuración? La parte importante aquí no es que no haya una línea en app.config, sino que no haya una información requerida.

Para mí, ConfigurationException (y su reemplazo, ConfigurationErrorsException, a pesar de los documentos engañosos de MSDN) son por errores al guardar, leer, etc. de Configuration.


He optado por InvalidOperationException, ya que es manejado por el método OnError protegido con la página ASP.NET, mientras que ConfigurationErrorsException y todas las excepciones derivadas de él no son
Mick

2
Esto realmente me sorprendería, si obtengo una InvalidOperationException si obtengo la configuración incorrecta.
keuleJ

18

Como dijo Daniel Richardson, ConfigurationErrorsException es el que se debe usar. En general, solo se recomienda crear sus propios tipos de excepción personalizados si tiene un escenario para manejarlos. En el caso de los errores de configuración, que generalmente son fatales, rara vez es así, por lo que suele ser más apropiado reutilizar el tipo ConfigurationErrorsException existente.

Antes de .NET 2.0, la recomendación era usar System.Configuration.ConfigurationException . ConfigurationException se volvió obsoleto en .NET 2.0, por razones que nunca fueron claras para mí, y la recomendación cambió para usar ConfigurationErrorsException.

Utilizo un método auxiliar para lanzar la excepción para que sea fácil cambiar la excepción que se lanza en un lugar al migrar de .NET 1.xa 2.0, o si Microsoft decide cambiar la recomendación nuevamente:

if(string.IsNullOrEmpty(Configuration.AppSettings("foobar")))
{
   throw CreateMissingSettingException("foobar");
}

...

private static Exception CreateMissingSettingException(string name)
{
    return new ConfigurationErrorsException(
        String.Format
        (
        CultureInfo.CurrentCulture,
        Properties.Resources.MissingConfigSetting,
        name
        )
        );
}

16

OMI, esta es la respuesta real. +1
LC

En realidad no, porque: proporciona una excepción para los objetos SettingsProperty que no se encuentran. Que proviene de: Utilizado internamente como la clase que representa metadatos sobre una propiedad de configuración individual. Lo cual no es lo mismo que un valor faltante de configuración.
Karol Haliński

7

ConfigurationErrorsExceptiones la excepción correcta para lanzar en la situación que describe. Una versión anterior de la documentación de MSDN ConfigurationErrorsExceptiontiene más sentido.

http://msdn.microsoft.com/en-us/library/system.configuration.configurationerrorsexception(VS.80).aspx

El resumen y las observaciones anteriores de MSDN son:

  • La excepción que se produce cuando se produce un error del sistema de configuración.
  • La ConfigurationErrorsException excepción se produce cuando se produce algún error mientras se lee o se escribe la información de configuración.

77
de la documentación: "Esta API es compatible con la infraestructura del producto y no está diseñada para ser utilizada directamente desde su código. Inicializa una nueva instancia de la clase ConfigurationErrorsException".
Oleg Sh

6

La clase ConfigurationElement (que es la clase base de muchas clases relacionadas con la configuración, como ConfigurationSection) tiene un método llamado OnRequiredPropertyNotFound (también hay otros métodos auxiliares). Tal vez puedas llamar a esos.

OnRequiredPropertyNotFound se implementa de la siguiente manera:

protected virtual object OnRequiredPropertyNotFound(string name) {
    throw new ConfigurationErrorsException(SR.GetString("Config_base_required_attribute_missing", new object[] { name }), this.PropertyFileName(name), this.PropertyLineNumber(name)); }

1

Lo succionaría y rodaría el mío ... pero antes de hacerlo, ¿es posible que el sistema asuma un valor predeterminado para esta configuración? Por lo general, intento hacer eso para cada configuración que podría perderse bu Ops Management folk ... (o tal vez debería decir, para tantas configuraciones como sea posible; para algunos claramente no es apropiado que el sistema tome una decisión predeterminada. ..)

en general, una excepción personalizada no es mucho esfuerzo ... aquí hay un ejemplo ...

[Serializable]
public class MyCustomApplicationException : ApplicationException
{
    #region privates
    #endregion privates

    #region properties
    #endregion properties

    public MyCustomApplicationException (string sMessage,
        Exception innerException)
        : base(sMessage, innerException) { }
    public MyCustomApplicationException (string sMessage)
        : base(sMessage) { }
    public MyCustomApplicationException () { }

    #region Serializeable Code
    public MyCustomApplicationException (
       SerializationInfo info, StreamingContext context)
        : base(info, context) { }
    #endregion Serializeable Code
}

2
MSDN: ... una aplicación que necesita crear sus propias excepciones, [...] derivar excepciones personalizadas de la clase Excepción. Originalmente se pensó que las excepciones personalizadas deberían derivarse de la clase ApplicationException; sin embargo, en la práctica no se ha encontrado que agregue un valor significativo.
Gaspar Nagy el

Sí, creo que fue porque los programadores de MS que codificaron el marco derivaron numerosas excepciones CLR de ApplicationException, lo que destruyó el significado de la distinción ... Todavía lo hago, ya que no veo ningún daño en él ...
Charles Bretana

1

Un método alternativo que podría usar para sus archivos de configuración sería usar secciones de configuración personalizadas en lugar de AppSettings. De esa manera, puede especificar que una propiedad IsRequiredy el sistema de configuración se encargarán de esta comprobación por usted. Si falta la propiedad, arrojará un, ConfigurationErrorsExceptionasí que supongo que respalda la respuesta de que debe usar esa excepción en su caso.


0

Mi regla general sería:

  1. Si el caso de la configuración que falta no es muy común y creo que nunca querría manejar este caso de manera diferente a otras excepciones, solo uso la clase básica "Excepción" con un mensaje apropiado:

    lanzar una nueva excepción ("mi mensaje aquí")

  2. Si quiero, o creo que hay una alta probabilidad de que quisiera manejar este caso de una manera diferente a la mayoría de las otras excepciones, rodaría mi propio tipo como la gente ya ha sugerido aquí.


0

Tiendo a estar en desacuerdo con la premisa de su pregunta:

En pocas palabras, necesito una excepción estándar que se debe lanzar cuando falta una configuración de la aplicación o contiene un valor no válido. Uno pensaría que el Framework tenía una excepción tal incorporada para que las aplicaciones lo usaran. (Aparentemente lo hizo, pero se marcó como obsoleto y fue reemplazado por algo mucho más amplio).

De acuerdo con la documentación de MSDN en System.Exception ( clase de excepción , realmente no debería lanzar excepciones para errores de entrada del usuario, por razones de rendimiento (lo cual ha sido señalado por otros en Stack Overflow y en otros lugares). Esto parece tener sentido ya que bien, ¿por qué su función no puede devolver falso si la entrada del usuario se ingresa incorrectamente y luego la aplicación sale correctamente? Esto parece ser más un problema de diseño que un problema con el que lanzar la excepción.

Como otros han señalado, si realmente tiene que lanzar una excepción, por alguna razón, no hay ninguna razón por la que no pueda definir su tipo de Excepción al heredar de System.Exception.


2
¿Por qué exactamente importaría el rendimiento en este escenario específico? IUC, entonces la excepción se produce exactamente una vez y el proceso probablemente se desactive después de todos modos (por supuesto, después de mostrar una buena ventana emergente al usuario). (continuará ...)

2
Devolver un código de error en lugar de lanzar una excepción podría ser doloroso, ya que luego tendría que propagar la información del error en la pila de llamadas usted mismo. Debería usar excepciones para errores relativamente raros que podrían propagarse en varios marcos de pila. Ambos se aplican aquí.

1
Te perdiste algo: "cuando falta una configuración de la aplicación o contiene un valor no válido", eso no es lo mismo que una entrada incorrecta del usuario. Esta es una configuración básica que falta. Debe ser una excepción personalizada y debe detener la ejecución de la aplicación.
jcollum

2
En esta aplicación en particular, está casi completamente impulsada por la configuración en el archivo de configuración. Si la configuración no está allí (donde está encriptada), la aplicación no puede continuar y debe finalizar. Se requiere virtualmente una excepción.
Mike Hofer el

1
Esto ciertamente puede entrar en la semántica, y la estructura de su código obviamente dictará la mejor implementación para su situación. Aún así, si tuviera un reinado libre en el diseño, todavía iría con un objeto para registrar el error y una salida elegante sobre una excepción, el rendimiento sea un problema o no.
Matt Jordan el

-2

Puede intentar heredar de la Excepción XML, o simplemente usarla.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.