En este primer video veremos cómo crear un proyecto en MVC, y como interacciona el controlador con la vista.
En este primer video veremos cómo crear un proyecto en MVC, y como interacciona el controlador con la vista.
Para contratar el servicio de timbrado comunícate al siguiente teléfono (33) 36581329 o al correo electrónico pintor@bioxor.com. Y si deseas un DESCUENTO diles que viste los videos de Héctor de León o hdeleon.
En este video te mostrare como timbrar el xml que en los videos anteriores construimos y sellamos.
Descargar proyecto hecho en el video: clic aquí.
Video 1: https://www.youtube.com/watch?v=XlTz0NRQLm4
Video 2: https://www.youtube.com/watch?v=HjfqdTspnio
Video 3: https://www.youtube.com/watch?v=qIr-LdCzfF0
Video 4: https://www.youtube.com/watch?v=suRypKtb7VU
Video 5: https://www.youtube.com/watch?v=FBcEeEpgwr0
Catálogos sat mysql: https://hdeleon.net/catalogos-para-facturar-3-3-sat-en-mysql/
class Program
{
//modifiquen por su path
static private string path = @"C:\Users\Bioxor\source\repos\Facturacion3.3-tutorial-hdeleon\";
static string pathXML = path + @"miPrimerXML.xml";
static void Main(string[] args)
{
//Obtener numero certificado------------------------------------------------------------
string pathCer = path+@"XSDToXML\CSD01_AAA010101AAA.cer";
string pathKey = path+@"XSDToXML\CSD01_AAA010101AAA.key";
string clavePrivada = "12345678a";
//Obtenemos el numero
string numeroCertificado, aa, b, c;
SelloDigital.leerCER(pathCer, out aa, out b, out c, out numeroCertificado);
//Llenamos la clase COMPROBANTE--------------------------------------------------------
Comprobante oComprobante = new Comprobante();
oComprobante.Version = "3.3";
oComprobante.Serie = "H";
oComprobante.Folio = "1";
oComprobante.Fecha = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");
// oComprobante.Sello = "faltante"; //sig video
oComprobante.FormaPago = "99";
oComprobante.NoCertificado = numeroCertificado;
// oComprobante.Certificado = ""; //sig video
oComprobante.SubTotal = 10m;
oComprobante.Descuento = 1;
oComprobante.Moneda = "MXN";
oComprobante.Total = 9;
oComprobante.TipoDeComprobante = "I";
oComprobante.MetodoPago = "PUE";
oComprobante.LugarExpedicion = "20131";
ComprobanteEmisor oEmisor = new ComprobanteEmisor();
oEmisor.Rfc = "LEGH870601DM7";
oEmisor.Nombre = "Una razón rh de cv";
oEmisor.RegimenFiscal = "605";
ComprobanteReceptor oReceptor = new ComprobanteReceptor();
oReceptor.Nombre = "Pepe SA DE CV";
oReceptor.Rfc = "BIO091204LB1";
oReceptor.UsoCFDI = "P01";
//asigno emisor y receptor
oComprobante.Emisor = oEmisor;
oComprobante.Receptor = oReceptor;
List<ComprobanteConcepto> lstConceptos = new List<ComprobanteConcepto>();
ComprobanteConcepto oConcepto = new ComprobanteConcepto();
oConcepto.Importe = 10m;
oConcepto.ClaveProdServ = "92111704";
oConcepto.Cantidad = 1;
oConcepto.ClaveUnidad = "C81";
oConcepto.Descripcion = "Un misil para la guerra";
oConcepto.ValorUnitario = 10m;
oConcepto.Descuento = 1;
lstConceptos.Add(oConcepto);
oComprobante.Conceptos = lstConceptos.ToArray();
//Creamos el xml
CreateXML(oComprobante);
string cadenaOriginal = "";
string pathxsl = path+ @"XSDToXML\cadenaoriginal_3_3.xslt";
System.Xml.Xsl.XslCompiledTransform transformador = new System.Xml.Xsl.XslCompiledTransform(true);
transformador.Load(pathxsl);
using (StringWriter sw= new StringWriter())
using (XmlWriter xwo= XmlWriter.Create(sw,transformador.OutputSettings)) {
transformador.Transform(pathXML, xwo);
cadenaOriginal = sw.ToString();
}
SelloDigital oSelloDigital = new SelloDigital();
oComprobante.Certificado = oSelloDigital.Certificado(pathCer);
oComprobante.Sello = oSelloDigital.Sellar(cadenaOriginal, pathKey, clavePrivada);
CreateXML(oComprobante);
//TIMBRE DEL XML
ServiceReferenceFC.RespuestaCFDi respuestaCFDI = new ServiceReferenceFC.RespuestaCFDi();
byte[] bXML = System.IO.File.ReadAllBytes(pathXML);
ServiceReferenceFC.TimbradoClient oTimbrado =new ServiceReferenceFC.TimbradoClient();
respuestaCFDI = oTimbrado.TimbrarTest("TEST010101ST1", "aaaaaa", bXML);
if (respuestaCFDI.Documento == null) {
Console.WriteLine(respuestaCFDI.Mensaje);
}
else
{
System.IO.File.WriteAllBytes(pathXML, respuestaCFDI.Documento);
}
}
private static void CreateXML(Comprobante oComprobante)
{
//SERIALIZAMOS.-------------------------------------------------
XmlSerializerNamespaces xmlNameSpace = new XmlSerializerNamespaces();
xmlNameSpace.Add("cfdi", "http://www.sat.gob.mx/cfd/3");
xmlNameSpace.Add("tfd", "http://www.sat.gob.mx/TimbreFiscalDigital");
xmlNameSpace.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlSerializer oXmlSerializar = new XmlSerializer(typeof(Comprobante));
string sXml = "";
using (var sww = new Utils.StringWriterWithEncoding(Encoding.UTF8))
{
using (XmlWriter writter = XmlWriter.Create(sww))
{
oXmlSerializar.Serialize(writter, oComprobante,xmlNameSpace);
sXml = sww.ToString();
}
}
//guardamos el string en un archivo
System.IO.File.WriteAllText(pathXML, sXml);
}
}
En este video te mostrare como contrarrestar los campos FieldSpecified creados en el primer video, poner el formato correcto de fecha, obtener la cadena original, obtener el campo certificado, poner los namespaces al xml, y por ultimo como sellar el xml con tu key.
Descargar proyecto hecho en el video: clic aquí.
Video 1: https://www.youtube.com/watch?v=XlTz0NRQLm4
Video 2: https://www.youtube.com/watch?v=HjfqdTspnio
Video 3: https://www.youtube.com/watch?v=qIr-LdCzfF0
Video 4: https://www.youtube.com/watch?v=suRypKtb7VU
Catálogos sat mysql: https://hdeleon.net/catalogos-para-facturar-3-3-sat-en-mysql/
Puedes preguntarme sobre programación aquí: https://www.youtube.com/watch?v=M84D75OcuUU
//CÓDIGO UTILIZADO EN EL VIDEO
class Program
{
//modifiquen por su path
static private string path = @"C:\Users\Bioxor\source\repos\Facturacion3.3-tutorial-hdeleon\";
static string pathXML = path + @"miPrimerXML.xml";
static void Main(string[] args)
{
//Obtener numero certificado------------------------------------------------------------
string pathCer = path+@"XSDToXML\CSD01_AAA010101AAA.cer";
string pathKey = path+@"XSDToXML\CSD01_AAA010101AAA.key";
string clavePrivada = "12345678a";
//Obtenemos el numero
string numeroCertificado, aa, b, c;
SelloDigital.leerCER(pathCer, out aa, out b, out c, out numeroCertificado);
//Llenamos la clase COMPROBANTE--------------------------------------------------------
Comprobante oComprobante = new Comprobante();
oComprobante.Version = "3.3";
oComprobante.Serie = "H";
oComprobante.Folio = "1";
oComprobante.Fecha = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");
// oComprobante.Sello = "faltante"; //sig video
oComprobante.FormaPago = "99";
oComprobante.NoCertificado = numeroCertificado;
// oComprobante.Certificado = ""; //sig video
oComprobante.SubTotal = 10m;
oComprobante.Descuento = 1;
oComprobante.Moneda = "MXN";
oComprobante.Total = 9;
oComprobante.TipoDeComprobante = "I";
oComprobante.MetodoPago = "PUE";
oComprobante.LugarExpedicion = "20131";
ComprobanteEmisor oEmisor = new ComprobanteEmisor();
oEmisor.Rfc = "POWE870601DM7";
oEmisor.Nombre = "Una razón rh de cv";
oEmisor.RegimenFiscal = "605";
ComprobanteReceptor oReceptor = new ComprobanteReceptor();
oReceptor.Nombre = "Pepe SA DE CV";
oReceptor.Rfc = "PEPE080801JH1";
oReceptor.UsoCFDI = "P01";
//asigno emisor y receptor
oComprobante.Emisor = oEmisor;
oComprobante.Receptor = oReceptor;
List<ComprobanteConcepto> lstConceptos = new List<ComprobanteConcepto>();
ComprobanteConcepto oConcepto = new ComprobanteConcepto();
oConcepto.Importe = 10m;
oConcepto.ClaveProdServ = "92111704";
oConcepto.Cantidad = 1;
oConcepto.ClaveUnidad = "C81";
oConcepto.Descripcion = "Un misil para la guerra";
oConcepto.ValorUnitario = 10m;
oConcepto.Descuento = 1;
lstConceptos.Add(oConcepto);
oComprobante.Conceptos = lstConceptos.ToArray();
//Creamos el xml
CreateXML(oComprobante);
string cadenaOriginal = "";
string pathxsl = path+ @"XSDToXML\cadenaoriginal_3_3.xslt";
System.Xml.Xsl.XslCompiledTransform transformador = new System.Xml.Xsl.XslCompiledTransform(true);
transformador.Load(pathxsl);
using (StringWriter sw= new StringWriter())
using (XmlWriter xwo= XmlWriter.Create(sw,transformador.OutputSettings)) {
transformador.Transform(pathXML, xwo);
cadenaOriginal = sw.ToString();
}
SelloDigital oSelloDigital = new SelloDigital();
oComprobante.Certificado = oSelloDigital.Certificado(pathCer);
oComprobante.Sello = oSelloDigital.Sellar(cadenaOriginal, pathKey, clavePrivada);
CreateXML(oComprobante);
}
private static void CreateXML(Comprobante oComprobante)
{
//SERIALIZAMOS.-------------------------------------------------
XmlSerializerNamespaces xmlNameSpace = new XmlSerializerNamespaces();
xmlNameSpace.Add("cfdi", "http://www.sat.gob.mx/cfd/3");
xmlNameSpace.Add("tfd", "http://www.sat.gob.mx/TimbreFiscalDigital");
xmlNameSpace.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlSerializer oXmlSerializar = new XmlSerializer(typeof(Comprobante));
string sXml = "";
using (var sww = new Utils.StringWriterWithEncoding(Encoding.UTF8))
{
using (XmlWriter writter = XmlWriter.Create(sww))
{
oXmlSerializar.Serialize(writter, oComprobante,xmlNameSpace);
sXml = sww.ToString();
}
}
//guardamos el string en un archivo
System.IO.File.WriteAllText(pathXML, sXml);
}
}
Te mostrare como comenzar de cero a utilizar Entity Framework, además a obtener, crear, editar y eliminar datos, y todo en menos de 10 minutos.
Existen varias formas de modificar varios elementos en conjunto por medio de Entity Framework.
Igual te recuerdo que utilizar EntityFramework.Extended como Entity Framework nativo no las recomiendo cuando vas a modificar más de mil datos, mejor utiliza un procedimiento almacenado.
La ventaja que veo al utilizar EntityFramework.Extended es un aspecto de sintaxis ya que de esta manera evitamos hacer el recorrido de los elementos e ir modificando objeto por objeto, con esta librería es de una forma más sencilla para el programador.
Para el siguiente ejemplo, supongamos que tenemos una tabla llamada Persona, que debemos modificar la edad a 10 años de todas las personas de Nombre “Juan”. Seria de la siguiente manera:
using(MiEntity db= new MiEntity()){
//realizamos la modificación sin foreach, ni SaveChanges()
db.Persona.Where(d => d.Nombre=="Juan")
.Update(x => new Persona() { Edad = 10 });
}
De esta manera no necesitamos el método SaveChanges(), ya que Update lo hace internamente.
Existen varias formas de modificar varios elementos en conjunto por medio de Entity Framework.
Te mostrare como realizar una forma de cómo hacerlo a continuación. Teniendo una tabla llamada Persona, supongamos que debemos modificar la edad a 10 años de todas las personas de Nombre “Juan”. Seria de la siguiente manera:
using(MiEntity db= new MiEntity()){
//Obtenemos todos los Juanes
IQuearyable<Persona> lst = db.Persona.Where(d=>d.Nombre=='Juan');
//recorremos la lista
foreach(Persona oPersona in lst){
//asignamos la edad
oPersona.Edad=10;
}
//modificamos los datos en la base de datos
db.SaveChanges();
}
Cuando tengas la necesidad de editar más de mil filas en un proceso, mejor hazlo con un procedimiento almacenado (Stored procedure).
Cuando se trabaja en un equipo de desarrollo que sobre pasa los 3 programadores muchas veces se debe obligar a que se realicen tareas básicas como recortar los espacios en las cadenas por medio de Trim, o quizá si existe un requerimiento del cliente de que todas las cadenas estén en mayúsculas realizar un ToUpper o por lo contrario un ToLower, bueno, cualquier función sobre algún tipo de dato en todos nuestros modelos de nuestra aplicación.
Para asegurarnos de que siempre sean ejecutadas este tipo de operaciones existe en MVC .Net algo llamado Binder o ModelBinder el cual trabaja como cubierta de la información y puede transformarla a lo que deseemos, validar o realizar una operación.
A continuación incluyo una clase la cual hará que todas las cadenas que existan en nuestros View Model se les aplique una función Trim y una función ToUpper, así evitamos ponerlas en todos los controles, haciendo que esto ya sea un proceso por defecto en toda la aplicación.
namespace Sistema.Models.Binders
{
public class TrimToUpperBinder : DefaultModelBinder
{
protected override void SetProperty(ControllerContext controllerContext,
ModelBindingContext bindingContext,
System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
{
//Solo modificaremos los string, por lo cual detectamos el tipo de dato
if (propertyDescriptor.PropertyType == typeof(string))
{
var stringValue = (string)value;
if (!string.IsNullOrEmpty(stringValue))
{
stringValue = stringValue.Trim(); //trimeamos
stringValue = stringValue.ToUpper(); //mayuscula
}
value = stringValue;
}
base.SetProperty(controllerContext, bindingContext,
propertyDescriptor, value);
}
}
}
Y para que sea ejecutado en toda la aplicación debemos inicializar nuestra clase en el archivo Global.asax en el método Application_Start() de la siguiente manera:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//Aquí remplazamos el binder por defecto con el nuestro
ModelBinders.Binders.DefaultBinder = new Sistema.Models.Binders.TrimToUpperBinder();
}
En este video describo como se puede generar las clases a partir de un archivo XSD.
También explico cómo convertir las clases en archivos XSD que tienen dependencia de otros archivos XSD.
Para ello aprovecho para generar las clases necesarias para crear el archivo XML que sirve para la facturación electrónica 3.3 del SAT en México.
Utilizaremos Visual Studio Command Prompt.
Si desean que haga un curso completo para la facturación electrónica, dime en los comentarios.
Te muestro como convertir un archivo PDF a un archivo Docx con dos librerías que tienen precio pero hacen su trabajo.
Código del ejemplo:
class Program
{
//ORIGEN PDF
static string pathPDF = @"C:\AlgunaRuta\archivo.pdf";
//DESTINOS ARCHIVO DOCX
static string pathDoc1 = @"C:\AlgunaRuta\archivo-spire.docx";
static string pathDoc2 = @"C:\AlgunaRuta\archivo-sautin.docx";
static void Main(string[] args)
{
//llamamos para convertir el pdf con spire
UsandoSpirePdf();
//llamamos para convertir el pdf con sautinsoft
UsandoSautin();
}
public static void UsandoSpirePdf()
{
PdfDocument pdf = new PdfDocument();
//cargamos el pdf
pdf.LoadFromFile(pathPDF);
//guardamos el docx
pdf.SaveToFile(pathDoc1, FileFormat.DOCX);
//abrimos el archivo
System.Diagnostics.Process.Start(pathDoc1);
}
public static void UsandoSautin()
{
SautinSoft.PdfFocus oPdfFocus = new SautinSoft.PdfFocus();
//cargamos el pdf
oPdfFocus.OpenPdf(pathPDF);
//si se tiene mas de 1 pagina
if (oPdfFocus.PageCount > 0)
{
//asignamos el tipo de documento al que convertiremos
oPdfFocus.WordOptions.Format = SautinSoft.PdfFocus.CWordOptions.eWordDocument.Docx;
//guardamos el dox
int resultado = oPdfFocus.ToWord(pathDoc2);
if (resultado == 0)
{
//abrimos el documento
System.Diagnostics.Process.Start(pathDoc2);
}
}
}
}
Spire.Pdf: https://www.e-iceblue.com/Introduce/pdf-for-net-introduce.html
SautinSoft.PdfFocus: http://www.sautinsoft.com/products/pdf-focus/
Cuando hacemos un módulo para actualizar una imagen, ya sea el logotipo o una galería, muchas veces tenemos el problema de que sigue saliendo en el navegador la imagen vieja hasta que borramos el cache del navegador.
Lamentablemente los usuarios no saben que es el cache y esperan ver su imagen nueva, al seguir viendo la imagen vieja, el usuario piensa que no se ha subido con éxito la nueva imagen.
En el caso de Mvc .Net esto re se resuelve con un truco, e igual puede resolverse con su equivalencia en cualquier otro lenguaje de programación.
Para esto vamos a hacer uso de la funcionalidad Random, funcionalidad que existe en todo lenguaje de programación y basta con hacerlo de la siguiente manera, en el caso de MVC .Net lo haremos en razor (en la vista):
@{
//creamos el objeto random y asignamos a una variable string
Random r = new Random();
string a = r.Next().ToString();
}
<img src='http://unsitio.com/unaimagen.jpg?a=@a'>
Al poner una variable con un valor nuevo al final de nuestra url de la imagen, obligamos al navegador a volver a cargarla y no utilizar la que tiene en cache.
Un truco viejo, pero que pocos conocen.