Monday, November 17, 2014

WCF – Service contract in a different project


I strongly recommend to implement service contracts in a separated project, why? Because in some scenarios I will need to share my contracts with external client applications, just because adding a "Web reference" is not a good idea, I agree it is easy, fast and can be updated from Visual Studio, but generated code is not managed by the developer & modify it is just a bug itself.
When adding a WCF Service application to your solution, your new project will looks like this:



The Visual Studio template has done all the job for you:
  • IService1 contains the service contract
  • Service1.svc.cs is the service it self
Ok, thanks Visual Studio for your help, but I prefer to do it by myself. First of all, "Service1" is not a proper name for a service, just remove the items generated by the Visual Studio and add a new WCF Service to your project (BusinessService in this example):



Once again, Visual Studio try to help me adding service contract and the service implementation in the project. This is not what I want so, I'm going to remove the IBusinessService, as I want it to be declared in a different project.
Add a new project "ToAllMicrosoftDevsOutThere.Service.Contracts" to your solution, the implementation of your service contract will be there, including DataContracts and MessageContracts. Following references must be added to your contracts project:
  • System.ServiceModel
  • System.Runtime.Serialization (for DataContracts/DataMember)
My service will contain just one operation (by now), defined on the service interface IBusinessService, which looks like:


[ServiceContract]
public interface IBusinessService
{
   [OperationContract]
   DoWorkResponse DoWork(DoWorkRequest request);
}

 

There are two interesting things on this interfaces:
  • My service interface must have the attribute 'ServiceContract'
  • All my service operations must have the attribute 'OperationContract'
Next step, my Service can receive complex objects as requests and send complex responses. These objects usually named DTO (Data Transfer Objects), should not contain any business logic, only properties (get/set) containing all the data my service needs in order to provide a response. For defining these DTO I will use MessageContracts:


[MessageContract]
public class DoWorkRequest
{
   [MessageBodyMember]
   public BusinessObjectDto BusinessEntity
   { get; set; }
}


[MessageContract]
public class DoWorkResponse
{
   [MessageBodyMember]
   public bool ItWasOk
   { getset}
}

 
In the previous code, I'm already using a DataContract (a data contract is a complex data type in my message contract):


[DataContract]
public class BusinessObjectDto
{
   [DataMember]
   public string Name
   { getset}
}

 
I need to add a reference to my contracts project on my service project and, now my projects structure looks like:



After adding the reference to my contracts project I can implement my Service contract on my service like follow:


namespace ToAllMicrosoftDevsOutThere.Service.Host
{
   public class BusinessService : IBusinessService
   {
      public DoWorkResponse DoWork(DoWorkRequest request)
      {
         return new DoWorkResponse() { ItWasOk true };
      }
   }
}

 
And that's all, just taking some minutes doing the setup of my WCF Service, I will be able to provide my Contract in a single DLL to any external application (.NET client…)
Enjoy coding!

Sunday, November 16, 2014

Basic solution structure in Visual Studio



This is just a quick note about the way I structure my solutions in Visual Studio, it is not a good practice or a standard, it is just the way I like to structure my solutions. 


Create the solution

I know you can create your first project and creating the solution at the same time, but, come on! You are going to create your solution only once, take the time (and the pleasure) for creating it properly.



Use solution folders

This is the best way for structure all you projects within the solution. I structure my projects in folders depending of the module they belong.



Order your folders

As you can see on the previous picture I have created a folder for each layer in my applications (Client & Service), personally I like order my projects from more external to deeper layer (understanding my database layer is the deeper one).



 

Enjoy coding

Now I have created my solution structure I can follow up writing other posts using this solution structure!

Sunday, November 2, 2014

NHibernate - Configuración




Partamos de un dominio sencillo: Autores literarios y sus libros, nuestro dominio sería algo como:


public class Author
{
   public virtual int Id
   { getset; }
   public virtual string FirstName
   { get; set; }

   public virtual string LastName

   { get; set; }

   public virtual IEnumerable<Book> Books

   { getset; }
}

 

public class Book
{
   public virtual int Id
   { getset; }
   public virtual string Title
   { get; set; }

   public virtual string Description
   { get; set; }

   public virtual Author Author

   { getset; }
}

Para asegurar la independencia de nuestro dominio de la tecnología que utilicemos para el acceso a datos, en este caso NHibernate, vamos a crear un nuevo proyecto y añadir la referencia a NHibernate en este nuevo proyecto. Además de la referencia a NHibernate, he añadido la una referencia a FluentNHibernate, para poder configurar mi dominio (prometo volver sobre el uso de Fluent en otro post).
En este momento nuestro proyecto tiene la estructura siguiente:







El siguiente pase es la configuración del mapping de NHibernate, para ello vamos a utilizar Fluent NHibernate. Cada objeto del dominio se mapea en una clase ClassMap de nuestro proyecto de acceso a datos:

 

public class AuthorMap : ClassMap<Author>

{
   public AuthorMap()
   {
      Id(x => x.Id)
               .Column("Id")
               .GeneratedBy.Identity();
      Map(x => x.FirstName).Column("FirstName").Not.Nullable();

      Map(x => x.LastName).Column("LastName").Nullable();
      HasMany(x => x.Books)
                    .KeyColumn("AuthorId")
                    .Inverse()
                    .Cascade.AllDeleteOrphan();
   }
}

 

public class BookMap : ClassMap<Book>

{
   public BookMap()
   {
      Id(x => x.Id)
               .Column("Id")
               .GeneratedBy.Identity();
      Map(x => x.Title).Column("Title").Not.Nullable();

      Map(x => x.Description).Column("Description").Nullable();
      References(x => x.Author).Column("AuthorId");
   }
}

Ya solo queda crear un proyecto de tests para probar nuestra configuracion, el test siguiente prueba el almacenamiento de un autor y su libro asociado


[TestClass]

public class DataTests

{

   private static ISessionFactory _sessionFactory;


    [TestInitialize]
   public void Init()
   {
      _sessionFactory Fluently.Configure()
                                .Database(MsSqlConfiguration.MsSql2012
                                .ConnectionString(x => x.FromConnectionStringWithKey("sample")))
                                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<AuthorMap>())
                                .BuildSessionFactory();
   }

    [TestMethod]
   public void SaveAuthor_Author_AuthorSaved()
   {
      var author new Author()
      {
         FirstName "Orson",
         LastName "Scott Card",
         Books new List<Book>() {
            new Book()
            {
               Description "Ender's Game is a 1985 military science fiction novel",
               Title"Ender's Game"

            }
         }
      };

      using (var session = _sessionFactory.OpenSession())

      using (var transaction = session.BeginTransaction())
      {
         session.SaveOrUpdate(author);
      }
   }
}


  

Friday, January 8, 2010

ASP.NET Llamar JavaScript desde C#


Voy a explicarte un ejemplo con un par de posibilidades para llamar a un método JavaScript desde tu código de servidor C#. La clave está en el método "RegisterStartupScript" que nos permite registrar un código JavaScript desde el código de C# y que éste sea interpretado por el navegador. Te puedes descargar el código de ejemplo aquí.
La primera posibilidad es que quieras invocar un método JavaScript desde el Page_Load de tu página ASPX, para ello puedes hacer lo siguiente:

 

///<summary>
/// Evento de carga de la página
///</summary>
///
<param name="sender"></param>

///
<param name="e"></param>

protected
void Page_Load(object sender, EventArgs e)

{
//Se llama a un javascript cuando la página carga
string mensaje = "Este mensaje se genera desde c#";
ClientScript.RegisterStartupScript(this.GetType(), "myScript", "<script>javascript:mostrarMensaje('" + mensaje + "');</script>");
}

 

La segunda posibilidad es que quieras ejecutar un método JavaScript desde el evento de un control de tu página ASPX:

 

///<summary>
///El botón va a ejecutar un código javascript
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
protected
void btnClick_Click(object sender, EventArgs e)

{
//Se genera el código javascript que se quiere ejecutar
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@"<script language='javascript'>");
sb.Append(@"var lbl = document.getElementById('lblMensaje');");
sb.Append(@"lbl.style.color='red';");
sb.Append(@"alert(lbl.innerText);");
sb.Append(@"</script>");

 
if (!ClientScript.IsStartupScriptRegistered("JSScript"))
{
ClientScript.RegisterStartupScript(this.GetType(), "JSScript", sb.ToString());
}
}

 

Espero que te sea de utilidad y recuerda que puedes descarte el código aquí.

ASP.NET Depurar JavaScript

En este post te voy a explicar cómo depurar un Java Script.

Depurarlo no es complicado, basta simplemente con incluir una instrucción "debugger;" dentro de tu código de JavaScript, de esta forma, cuando este código pase a ejecutarse el depurador de Visual Studio se parará tal como lo hace en un break-point de tu código C#.


 

<script language="javascript" type="text/javascript">

function mostrarMensaje(mensaje)

{

debugger;

alert(mensaje);

}

</script>


 

Como puedes ver en la siguiente imagen Visual Studio te permite incluso de explorar los valores de tus variables dentro de tu JavaScript:



 

Espero que te sirva!

Wednesday, January 6, 2010

ASP.NET Ajax - Añadir triggers a un UpdatePanel dinámicamente

Este post te será útil en el caso de que estés interesado en añadir eventos como triggers de Update Panels programáticamente en tiempo de ejecución.

Cuando se añaden Triggers a un update panel en tiempo de diseño, el aspecto de nuestra página será el siguiente:


 

<asp:UpdatePanel
ID="UpdatePanel1"
runat="server"
ChildrenAsTriggers="False"
UpdateMode="Conditional">

<ContentTemplate>

<asp:Button
ID="BtnAcceptar"
runat="server"
Text="Aceptar"
OnClick="BtnAcceptar_Click"
/>

</ContentTemplate>

<Triggers>

<asp:AsyncPostBackTrigger
ControlID="BtnAcceptar"
EventName="Click"
/>

</Triggers>

</asp:UpdatePanel>


 

Si tus necesidades precisan que estos triggers sean añadidos en tiempo de ejecución utiliza el siguiente código:


 

AsyncPostBackTrigger Trigger = new
AsyncPostBackTrigger();

//ControlID = ID del control que provoca el evento.

Trigger.ControlID = ControlID;

//EventName = Nombre del evento, p.e: Click, SelectedIndexChange.

Trigger.EventName = EventName;

//Se añade el trigger al update panel

UpdatePanel1.Triggers.Add(Trigger);


 

Espero que te sea de utilidad!

.NET Log en el Visor de Sucesos (Event Viewer)

En este post quiero mostrarte como utilizar el visor de sucesos como para persistir los eventos de tu aplicación.

El soporte de Microsoft dice lo siguiente:

"Los registros de sucesos proporcionan un medio estándar y centralizado para que las aplicaciones graben sucesos (eventos) de software y hardware importantes. Windows suministra una interfaz de usuario estándar para ver los registros: el Visor de sucesos" (aquí)

No quiero contradecirlos pero, en mi opinión, no tendríamos que abusar del uso del registro de sucesos por las siguientes razones:

  1. El registro de sucesos se llena. A mí ya me ha ocurrido en una máquina XP, entiendo que en un servidor el tamaño será mucho más grande.
  2. La explotación de estadísticas. Es habitual querer obtener estadísticas de los eventos que provocan nuestras aplicaciones.
  3. Mantenimiento de aplicaciones. El Visor de Sucesos muestra los eventos escritos por todas las aplicaciones del sistema, por tanto es más difícil encontrar el evento que buscamos.

Mi recomendación sería usar una base de datos para persistir nuestros logs del tipo que sean (auditoría, errores, informativos…), para poder explotar estos datos. Aún así, los eventos informados en el registro de sucesos dan un aspecto más profesional a nuestras aplicaciones, pudiendo seleccionar ciertos eventos de nuestra aplicación que deberíamos persistir en el registro de eventos.

El uso es sencillo lo podéis ver aquí.

Sólo tienes que crear un nuevo proyecto usando la plantilla de "Aplicación del Consola" y tener el código siguiente en tu clase Main:


 

static
void Main(string[] args)

{

string sSource;

string sLog;

string sEvent;


 

sSource = "Nombre de mi aplicación";

sLog = "Application";

sEvent = "Mensaje de nuestro evento";

//Se añade nuestra aplicación como generadora de eventos si esta no existe

if (!EventLog.SourceExists(sSource))

{

EventLog.CreateEventSource(sSource, sLog);

}


 

//Se escribe una Advertencia/Warning

EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Warning, 230);

//Se escribe un error

EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Error, 231);

//Se escribe un error

EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.FailureAudit, 232);

//Se escribe un error

EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Information, 233);

//Se escribe un er

EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.SuccessAudit, 234);

}


 

Una vez ejecutes la aplicación consulta el visor de sucesos de tu máquina: Inicio > Ejecutar >eventvwr. Este tendrá el aspecto que puedes ver en la imagen siguiente:


 



 

Espero que te sea útil este post y si tienes alguna duda realiza un comentario.