2009-07-13 14 views
24

Estoy usando VSTS 2008 + C# + .Net 2.0. Al ejecutar la siguiente declaración, se lanza FormatException de la declaración String.Format, ¿alguna idea de qué es lo que está mal?Excepción de String.Format cuando la cadena de formato contiene "{"

Aquí es donde conseguir la plantilla.html que estoy usando. Quiero formatear esta parte m = {0} en template.html.

string template = String.Empty; 
    using (StreamReader textFile = new StreamReader("template.html")) 
    { 
     template = textFile.ReadToEnd(); 
     String.Format(template, "video.wmv"); 
    } 

http://www.mediafire.com/download.php?u4myvhbmmzg

EDIT 1:

Aquí es el contenido de mi template.html,

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<!-- saved from url=(0014)about:internet --> 
<head> 
    <title>Silverlight Project Test Page </title> 

    <style type="text/css"> 
    html, body { 
     height: 100%; 
     overflow: auto; 
    } 
    body { 
     padding: 0; 
     margin: 0; 
    } 
    #silverlightControlHost { 
     height: 100%; 
    } 
    </style> 

    <script type="text/javascript"> 
     function onSilverlightError(sender, args) { 

      var appSource = ""; 
      if (sender != null && sender != 0) { 
       appSource = sender.getHost().Source; 
      } 
      var errorType = args.ErrorType; 
      var iErrorCode = args.ErrorCode; 

      var errMsg = "Unhandled Error in Silverlight 2 Application " + appSource + "\n" ; 

      errMsg += "Code: "+ iErrorCode + " \n"; 
      errMsg += "Category: " + errorType + "  \n"; 
      errMsg += "Message: " + args.ErrorMessage + "  \n"; 

      if (errorType == "ParserError") 
      { 
       errMsg += "File: " + args.xamlFile + "  \n"; 
       errMsg += "Line: " + args.lineNumber + "  \n"; 
       errMsg += "Position: " + args.charPosition + "  \n"; 
      } 
      else if (errorType == "RuntimeError") 
      {   
       if (args.lineNumber != 0) 
       { 
        errMsg += "Line: " + args.lineNumber + "  \n"; 
        errMsg += "Position: " + args.charPosition + "  \n"; 
       } 
       errMsg += "MethodName: " + args.methodName + "  \n"; 
      } 

      throw new Error(errMsg); 
     } 
    </script> 
</head> 

<body> 
    <!-- Runtime errors from Silverlight will be displayed here. 
    This will contain debugging information and should be removed or hidden when debugging is completed --> 
    <div id='errorLocation' style="font-size: small;color: Gray;"></div> 

    <div id="silverlightControlHost"> 
     <object data="data:application/x-silverlight," type="application/x-silverlight-2" width="500" height="240"> 
      <param name="source" value="ClientBin/VideoPlayer.xap"/> 
      <param name="onerror" value="onSilverlightError" /> 
      <param name="background" value="white" /> 
      <param name="initParams" value="cc=true,markers=true,m={0}" /> 
      <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;"> 
       <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/> 
      </a> 
     </object> 
     <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe> 
    </div> 
</body> 
</html> 

gracias en avdance, George

+1

Como se sospecha, hay llaves en los estilos y el javascript. Eso no funcionará a menos que los escape, como cadena. El formato encuentra un {y entra en pánico cuando no puede encontrar un entero y un}. –

+2

por cierto; Actualmente no está capturando el resultado de la cadena. Formato (cadenas .NET son inmutables, por lo que string.Format devuelve una cadena ** nueva **; no actualiza la cadena de entrada) –

+0

(respondió al comentario) –

Respuesta

48

En una conjetura, el html contiene javascript u otra fuente de sujetador ces ({ y }) que todos necesitarían doblar (a {{ y }}) para usar con string.Format. Espero que un token diferente (más obvio) esté en orden, es decir, %%FILENAME%%. Luego use ya sea regex o string.Replace.

Si tiene una sola etiqueta, string.Replace está bien; si tiene lotes, existen trucos con regex y MatchEvaluator que pueden ser útiles: like so pero con un patrón de expresiones regulares diferente.


Actualizar después del html de ejemplo agregado: Definitivamente usaría un token diferente; en el nivel más básico:

<param name="initParams" value="cc=true,markers=true,m=%%FILENAME%%" /> 

y

template = template.Replace("%%FILENAME%%", "video.wmv"); 
+2

I second este control para otras llaves. –

+0

Cool, Marc, me gusta tu solución inteligente. – George2

+0

Marc, ¿podría explicar qué quiere decir con "todos necesitarían doblar (a {{y}}) para poder usarlo con cadena. Formato", estoy confundido, lo que significa que es necesario doblar para poder usarlo con cadena. Formato. – George2

1

Wat son los contenidos de la variable 'plantilla'?

Difícil de decir cuál es el problema con su código, pero presumiblemente, la variable de la plantilla no contiene una cadena que ocupe un lugar. (como "esto es una cadena {0}").

Creo que debe hacer uso de las herramientas que su IDE proporciona: depure el código, use relojes para inspeccionar el contenido de la variable de la plantilla.

+0

Tengo publiqué mi plantilla.html en mi publicación original en la sección EDITAR 1, ¿alguna idea de qué es lo que está mal? – George2

0

¿Qué hay en el archivo de plantilla?

si hay llaves que no son del formato {int} o hay más de los que hay argumentos para la declaración de formato, lanzará una excepción.

¿Cuál es el mensaje en la excepción?

Es su Css eso es hacerlo. Como somoene más ha dicho que necesita para DOA expresiones regulares sustituir, o un montón de String.Replace comandos en una fila que marca las variables con %% %% VARIABLE_NAME uso y sustitución de cadena para reemplazarlos

+0

He publicado mi plantilla.html en mi publicación original en la sección EDITAR 1, ¿qué ideas hay de las incorrectas? – George2

+1

No tener {0} no causa una excepción. Los parámetros simplemente serán ignorados. –

+0

eliminó esa cláusula. –

12

Su plantilla contiene { y } caracteres que deben ser escapados, de lo contrario confunden String.Format. Escápelos usando {{ y }}.Alternativamente, use un mecanismo diferente como String.Replace.

+0

He publicado mi plantilla.html en mi publicación original en la sección EDITAR 1, ¿qué ideas hay de las incorrectas? – George2

+1

las llaves. –

+0

Frederik, la solución es? – George2

6

string.Format() no controla { y } en la cadena de formato. Debe reemplazar { con {{ y } con }} en todas partes en su archivo template.html. Excepto por el único lugar donde usa el marcador de posición {0}.

No muy elegante.

En su lugar, considere el uso de un motor de plantillas. Consulte http://csharp-source.net/open-source/template-engines para obtener algunas sugerencias.

La siguiente mejor solución es usar expresiones regulares (con MatchEvaluator) o string.Replace(), como lo sugieren otras respuestas.

Editar:

Aquí hay un ejemplo usando el motor de plantillas StringTemplate:

StringTemplate htmlpage = new StringTemplate(File.ReadAllText("template.html")); 
htmlpage.SetAttribute("content", "video.wmv"); 
Console.WriteLine(htmlpage.ToString()); 

cambiar una sola línea en su archivo template.html:

de:

<param name="initParams" value="cc=true,markers=true,m={0}" /> 

a:

<param name="initParams" value="cc=true,markers=true,m=$content$" /> 

Cuando el motor de plantillas encuentra $content$ en la plantilla, se lo reemplaza con el valor del 'contenido' que atribuyen configurado con código.

Usando StringTemplate, puede hacer bucles simples y condicionales dentro de su plantilla. Ver the documentation.

+1

De acuerdo. string.Format es un motor de plantillas pésimo debido a la forma en que maneja llaves ({y}). –

+0

Hola codeape, estudié el motor de plantillas, pero ¿por qué y cómo se relaciona el motor de la plantilla con mi pregunta? – George2

+0

Hola Joe, ¿cómo se relaciona el motor de la plantilla con mi pregunta? Estoy confundido, ¿algún comentario? – George2

Cuestiones relacionadas