by Fujiy
28. junho 2010 23:28
Os validator RangeValidator e CompareValidator permitem validar se o texto digitado pode ser convertido para um certo tipo, como DateTime. Porém em browsers não IE ocorre um erro de javascript quando se usa datas com 2 dígitos no ano. Para corrigir isto pode-se usar o seguinte javascript para sobrescrever o método original:
function ValidatorConvert(op, dataType, val) {
function GetFullYear(year) {
var twoDigitCutoffYear = val.cutoffyear % 100;
var cutoffYearCentury = val.cutoffyear - twoDigitCutoffYear;
return ((year > twoDigitCutoffYear) ? (cutoffYearCentury - 100 + year) : (cutoffYearCentury + year));
}
var num, cleanInput, m, exp;
if (dataType == "Integer") {
exp = /^\s*[-\+]?\d+\s*$/;
if (op.match(exp) == null)
return null;
num = parseInt(op, 10);
return (isNaN(num) ? null : num);
}
else if (dataType == "Double") {
exp = new RegExp("^\\s*([-\\+])?(\\d*)\\" + val.decimalchar + "?(\\d*)\\s*$");
m = op.match(exp);
if (m == null)
return null;
if (m[2].length == 0 && m[3].length == 0)
return null;
cleanInput = (m[1] != null ? m[1] : "") + (m[2].length > 0 ? m[2] : "0") + (m[3].length > 0 ? "." + m[3] : "");
num = parseFloat(cleanInput);
return (isNaN(num) ? null : num);
}
else if (dataType == "Currency") {
var hasDigits = (val.digits > 0);
var beginGroupSize, subsequentGroupSize;
var groupSizeNum = parseInt(val.groupsize, 10);
if (!isNaN(groupSizeNum) && groupSizeNum > 0) {
beginGroupSize = "{1," + groupSizeNum + "}";
subsequentGroupSize = "{" + groupSizeNum + "}";
}
else {
beginGroupSize = subsequentGroupSize = "+";
}
exp = new RegExp("^\\s*([-\\+])?((\\d" + beginGroupSize + "(\\" + val.groupchar + "\\d" + subsequentGroupSize + ")+)|\\d*)"
+ (hasDigits ? "\\" + val.decimalchar + "?(\\d{0," + val.digits + "})" : "")
+ "\\s*$");
m = op.match(exp);
if (m == null)
return null;
if (m[2].length == 0 && hasDigits && m[5].length == 0)
return null;
cleanInput = (m[1] != null ? m[1] : "") + m[2].replace(new RegExp("(\\" + val.groupchar + ")", "g"), "") + ((hasDigits && m[5].length > 0) ? "." + m[5] : "");
num = parseFloat(cleanInput);
return (isNaN(num) ? null : num);
}
else if (dataType == "Date") {
var yearFirstExp = new RegExp("^\\s*((\\d{4})|(\\d{2}))([-/]|\\. ?)(\\d{1,2})\\4(\\d{1,2})\\s*$");
m = op.match(yearFirstExp);
var day, month, year;
if (m != null && m.length > 2 && m[2] && (m[2].length == 4 || val.dateorder == "ymd")) {
day = m[6];
month = m[5];
year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10))
}
else {
if (val.dateorder == "ymd") {
return null;
}
var yearLastExp = new RegExp("^\\s*(\\d{1,2})([-/]|\\. ?)(\\d{1,2})\\2((\\d{4})|(\\d{2}))\\s*$");
m = op.match(yearLastExp);
if (m == null) {
return null;
}
if (val.dateorder == "mdy") {
day = m[3];
month = m[1];
}
else {
day = m[1];
month = m[3];
}
year = (m[5] && m[5].length == 4) ? m[5] : GetFullYear(parseInt(m[6], 10))
}
if (Number(year) > 0 && Number(month) > 0 && Number(day) > 0) {
month -= 1;
var date = new Date(year, month, day);
if (year < 100) {
date.setFullYear(year);
}
return (typeof (date) == "object" && year == date.getFullYear() && month == date.getMonth() && day == date.getDate()) ? date.valueOf() : null;
}
else
return null;
}
else {
return op.toString();
}
}
1e9e3a30-97ae-4223-abb4-18dc58ec90db|0|.0
Tags:
Artigos
by Fujiy
13. janeiro 2010 08:41
Os tipos anônimos introduzidos no C# 3.0 para facilitar o uso do LINQ agilizam o desenvolvimento, evitando que tenhamos que declarar uma classe em casos específicos.
Mas esses tipos tem alguma limitações, intencionais, por exemplo, não podemos usar os tipos gerados como retorno ou parâmetro de um método. Até porque os tipos gerados são internal.
O desafio é retornar um tipo anônimo e usá-lo no seu código, sem usar Reflection. Não tem uso prático, já que não é uma boa prática fazer isso, mas serve como exercício.
Para adiantar, vou postar o método que faz o retorno:
public static object RetornaAnonimo()
{
return new {Id = 1, Nome = "João"};
}
Agora resta conseguir usar o tipo numa chamada. Ex.:
var retorno = RetornaAnonimo();
....
by Fujiy
24. setembro 2009 23:10
Considerando o seguinte código, qual será o resultado?
class Program
{
static void Main()
{
Derived c = new Derived();
c.Metodo(1);
}
}
public class Base
{
public void Metodo(int a)
{
Console.WriteLine("Int32 / " + a.GetType());
}
}
public class Derived:Base
{
public void Metodo(object a)
{
Console.WriteLine("Object / " + a.GetType());
}
}
by Fujiy
14. agosto 2009 11:24
As seguintes classes geram o mesmo resultado? Se não, por quê?
public class A
{
public static string X = "A";
}
public class A
{
public static string X;
static A()
{
X = "A";
}
}
Teoricamente deveriam ser iguais, mas a segunda classe é equivalente à:
public class A
{
public static string X = "A";
static A()
{
}
}
A diferença está existência ou não do construtor. Quando não há construtor a classe é marcada como beforefieldinit, fazendo com que o type initializer seja chamado antes mesmo de qualquer referência à algum membro da classe.
Podemos perceber isso com o seguinte código:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Iniciando");
A.Escrever("Escrever");
Console.WriteLine("Depois de escrever");
string y = A.X;
Console.WriteLine("Depois de acessar o campo X");
Console.ReadKey();
}
}
public class A
{
public static string X = Escrever("X (Type Initializer)");
public static string Escrever(string s)
{
Console.WriteLine(s);
return s;
}
}
Antes de qualquer coisa, o tipo já é inicializado. Mas se você criar um construtor, mesmo que vazio, a ordem das chamadas vai mudar.
O Type Initializer só é executado antes da primeira referência ao tipo. No caso antes do A.Escrever("Escrever").
Curioso, e pode gerar um comportamento inesperado.
by Fujiy
7. julho 2009 09:03
Sempre pensei que um número no formato *.5 arredondava para cima, mas na verdade arredonda pro número par mais próximo. Por exemplo:
Console.WriteLine(Math.Round(4.4)); // 4
Console.WriteLine(Math.Round(4.5)); // 4
Console.WriteLine(Math.Round(4.6)); // 5
Console.WriteLine(Math.Round(5.5)); // 6
Este tipo de método se chama Banker's rounding
by Fujiy
1. julho 2009 14:53
Sendo:
int i1 = valorx;
int i2 = valory;
Como trocar os valores das variaveis sem criar outra variavel temporária?
A resposta está nos comentários.
by Fujiy
17. junho 2009 14:33
Uma dica que pode ajudar muito:
Imagine que temos um relacionamento da tabela Mensagem com a Usuario, normalmente fariamos o seguinte para criar um relacionamento:
Mensagem mens = new Mensagem();
mens.Usuario = from us in contexto.UsuarioSet
where us.Id = 10
select us;
contexto.AddToMensagemSet(mens);
contexto.SaveChanges();
O problema é fazemos uma consulta no banco somente para criar o relacionamento, sendo que já temos a informação necessária para isso, o Id do Usuario.
Existe uma outra forma de fazer isso sem consultar o banco de dados:
Mensagem mens = new Mensagem();
mens.UsuarioReference.EntityKey = new EntityKey("YourEntitiesModel.UsuarioSet", "Id", 10);
contexto.AddToMensagemSet(mens);
contexto.SaveChanges();
Assim economizamos um Select, o que faz a diferença quando temos muitas chamadas
by Fujiy
9. fevereiro 2009 07:25
Agora com a versão Release Candidate do ASP.NET MVC resolvi começar a estudar sobre o assunto.
Como ainda sou usuário e fã do Windows XP, já imaginei que poderia ter problemas com o IIS 6.0. Acontece que o IIS só passa pro ASP.NET as chamadas que estão configuradas para isso, usando a extensão do arquivo. Então quando você chama a página /Home/About o ASP.NET nem fica sabendo, o IIS logo fala que a página não existe.
Você tem duas opções pra resolver o problema. Uma é adicionar um redirecionamento pro ASP.NET usando o wildcard *, isso faz com que todas as chamadas sejam enviados pro ASP.NET, o que terá impacto no desempenho geral do seu site.
A outra opção, que considero melhor, apesar de alterar sua URL é usar a extensão .aspx nas URLs, /Home/About será /Home.aspx/About. Além de não impactar no desempenho, na maioria das vezes é sua única opção pra quem usa hospedagem compartilhada e não tem acesso ao servidor.
Como o ASP.NET MVC cria os links quando você usa o Html.ActionLink, a única alteração necessária é no Global.asax, onde você vai apagar a rota padrão, e adicionar as seguinte:
routes.MapRoute(
"Default",
"{controller}.aspx/{action}/{id}",
new { action = "Index", id = "" }
);
routes.MapRoute(
"Root",
"",
new { controller = "Home", action = "Index", id = "" }
);
A segunda é apenas para o diretório raiz funcionar.
Depois de mudar o Global.asax basta compilar e atualizar o servidor que já vai funcionar!
by Fujiy
6. fevereiro 2009 14:14
Uma dica pra quem quiser executar um script sempre após o update do Ajax no Asp.Net.
Alguem scripts não funcionam se você envia-los pelo ScriptManager, pois precisam ser executados após a requisição do Ajax ser terminada e fechada. É o caso do PNGFix pro Internet Explorer 6.0.
Se você carregar imagens no seu UpdatePanel, o PNGFix não funciona pras novas imagens, mesmo mandando executar novamente pelo ScriptManager, esta foi a única alternativa que encontrei.
É simples, adicione a seguinte chamado ao body:
<body onload=" RegisterEndRequest()">
E adicione o script na sua página:
function RegisterEndRequest() {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
}
function EndRequestHandler() {
$('.imagem').pngFix();
}
A primeira função é a que será chamada pelo onload do body, ela vai registrar a outra função para que seja executada sempre que terminar um update do Ajax. Na EndRequestHandler você coloca o seu código.
Simples!
by Fujiy
16. julho 2008 11:46
Vou propor um desafio: Qual o resultado do seguinte código? E por quê?
public class MainClass
{
static bool DeveMudar = false;
public static void Main()
{
Console.WriteLine(DeveMudar);
MetodoQualquer();
Console.WriteLine(DeveMudar);
Console.ReadKey();
}
public static IEnumerable<int> MetodoQualquer()
{
DeveMudar = true;
yield return 1;
}
}