Pergunta

Há muitas postagens e explicações muito boas sobre como implementar a validação com o ASP.NET MVC, e eu prefiro um deles:

No entanto, eu realmente gosto de ligar para os métodos de ação via método jQuery $ .ajax. Uma das razões pelas quais eu quero usar $ .ajax é porque haverá muitas visualizações parciais carregadas na página dinamicamente (mesmo o formulário para criação de entidades) via $ .ajax chamadas e não posso simplesmente devolver a visualização - Vou perder todo o conteúdo carregado dinamicamente.

Para fornecer uma visão melhor sobre o problema, postarei um código simples para explicar como gostaria de chamar de ação dos controladores e lidar com respostas no cliente, código jQuery.

O Controllers ActionMethod:

    public ActionResult CreateCustomer(string name, string accountNumber)
    {
        try
        {
            CustomerService.InsertCustomer(name, accountNumber);

            return Json(new ActionInfo()
            {
                Success = true,
                Message = "Customer Is Successfully Created"
            });

        }
        catch (Exception ex)
        {
            return Json(new ActionInfo()
            {
                Success = false,
                Message = ex.Message
            });
        }
    }

Chamando e manuseio no código do cliente:

$.ajax({
type: "POST",
url: $form.attr('action'),// /MyController/CreateCustomer
data: $form.serialize(),
error: HandleUnespectedError,
dataType: "json",
success: function(response) {

    if (response.Success)
        alert("Success: " + response.Message);
    else
        alert("Error: " + response.Message);
}});

Existe uma boa maneira de fazer algumas dessas estruturas de validação para funcionar da maneira que eu preciso? Sei que posso adicionar erros de validação no ActionInfo e, em seguida, lidar com isso no cliente, mas isso já seria um edifício da minha única validação, acredito.

Foi útil?

Solução

Tive um grande sucesso fazendo validação via AJAX usando atributos de anotações de dados. Para verificar a validade dos seus dados, você deseja usar o controlador ModelState propriedade, que tem uma propriedade própria chamada IsValid. Eu sugiro fortemente dar uma olhada no Anotações de dados Tutorial de atributos de validação No site oficial do ASP.NET MVC.

Primeiro, você deseja modificar sua ação do controlador para aceitar seu objeto modelo como um parâmetro, em vez de um nome e número de conta separados. Isso fará com que a realização da validação, que demonstrarei abaixo, muito mais simples. Pelo seu exemplo, meu melhor palpite é que seu objeto modelo é ou seria chamado de cliente. Você pode ter o seguinte código para definir o objeto modelo e sua ação do controlador ...

// model object
public class Customer
{
  public Int32 Id {get; set;}
  public String Name {get; set;}
  public String AccountNumber {get; set;}
}

// controller
public class CustomerController : Controller
{
  public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
  {
     // controller action code
  }
}


Verifique se seus campos de formulário são nomeados para corresponder aos nomes das propriedades do objeto do cliente para que o ASP.NET MVC possa ligá -los automaticamente. O atributo "Bind", neste caso, está dizendo ao ASP.NET MVC para ignorar a propriedade "ID" da classe do cliente ao vincular campos para modelar propriedades. Como este é um novo cliente, ainda não temos um ID, para que possamos deixar o ID com segurança como qualquer que seja o valor padrão e deixar a camada de dados para descobrir a melhor forma de gerá -lo.

Uma vez que o controlador tenha construído o objeto modelo para o método de ação, sua validade pode ser facilmente verificada através do ModelState.IsValid propriedade. Como se poderia esperar, ele retornará se as propriedades do modelo forem válidas ou falsas se 1 ou mais propriedades forem inválidas.

Da pergunta original, parece que o CustomerService.InsertCustomer O método está lançando exceções quando a validação falha. Isso é completamente desnecessário. O InsertCustomer deve precisar executar apenas quaisquer operações de dados necessárias para inserir o novo registro. A menos que você queira abstrair exceções específicas da implementação, como o SQLEXCECCECIONE, o InsertCustomer não deve realmente precisar capturar ou lançar nenhuma exceção, mas provavelmente pode deixar que qualquer exceção borbulhe até o controlador (ou quem quer que seja o chamador).

O resultado final de tudo isso, pode ser uma ação do controlador que se parece com o seguinte:

public ActionResult CreateCustomer( [Bind(Exclude = "Id")] Customer customer )
{
  // model is invalid
  if (!ModelState.IsValid)
  {
    return Json(new ActionInfo()
    {
      Success = false,
      Message = "Validation failed" // you will probably want a more robust message :-)
    });
  }

  // service method accepts a Customer object rather than arbitrary strings  
  CustomerService.InsertCustomer(customer);

  return Json(new ActionInfo()
  {
    Success = true,
    Message = "Customer created successfully."
  });

}


Se você deseja relatar erros inesperados, como exceções relacionadas ao banco de dados, certamente poderá adicionar um bloco de tentativa/captura em torno da chamada ao InsertCustomer e retornar o resultado necessário para exibir a mensagem de erro de volta ao cliente.

Outras dicas

Isso é mais de um ano depois que você fez sua pergunta, mas eu cobri a validação do lado do servidor com chamadas de Ajax no meu Postagem do blog Isso pode ser de muito interesse para você. Vejo que você retorna os resultados falhados como chamadas HTTP bem -sucedidas. Eu lidei de maneira diferente (acho que é mais correto desde $.ajax tem a capacidade de success e error funcionalidade de resposta). E seu exemplo específico é um exemplo perfeito que pode ser implementado com a funcionalidade que explico na minha postagem no blog.

Basicamente, em vez de sempre retornar uma resposta bem -sucedida (mas com propriedades definidas para dizer ao cliente que o processamento lateral do servidor falhou), prefiro fazer uma execução no servidor e lidar com ele de acordo com o cliente. Estou usando uma classe ModelStateException personalizada junto com um HandleModelStateException filtro de ação.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top