Como posso capturar um erro de procedimento armazenado SQL acionado pelo raiseError () no arquivo .asmx?

StackOverflow https://stackoverflow.com/questions/1104725

Pergunta

Eu estou muito novo para .net. Tudo o que fiz até agora é implementar algumas chamadas de procedimento armazenadas do SQL como serviços da web, copiando e colando o código existente (conforme instruído pelo meu superior).

Estou chamando alguns comandos via Database.ExecuteNonQuery(). No procedimento armazenado do SQL, estou realizando algumas verificações de segurança com base no loginid (um usuário pode editar apenas itens dos quais eles são o proprietário). Se a verificação de segurança falhar, estou chamando RaiseError () para acionar um erro, mas meu arquivo .asmx não está vendo isso como uma exceção e simplesmente sai do procedimento armazenado.

Meu arquivo ASMX:

[WebMethod]
public XmlDocument UpdateSomeItem(Int32 ItemIdNmb, String Foo)
{
    try
    {

        // Create the Database object, using the default database service. The
        // default database service is determined through configuration.
        Database db = DatabaseFactory.CreateDatabase();
        DbParameter param;

        string sqlCommand = "updateSomeItem";
        DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);

        db.AddInParameter(dbCommand, "ItemIdNmb", DbType.Int32, ItemIdNmb);
        db.AddInParameter(dbCommand, "Foo", DbType.String, Foo);
        db.AddInParameter(dbCommand, "UpdateLoginIdNmb", DbType.Int32, SessionLoginIdNmb);

        #region Return Parameter
        param = dbCommand.CreateParameter();
        param.ParameterName = "Return";
        param.Direction = ParameterDirection.ReturnValue;
        param.DbType = DbType.Int32;

        dbCommand.Parameters.Add(param);
        #endregion

        // Execute the Command
        db.ExecuteNonQuery(dbCommand);

        myDataSet = new DataSet();

        myDataSet.DataSetName = "DataSet";
        myDataSet.Tables.Add(errorDataTable);

        statusDataRow["Status"] = "Success";
        statusDataTable.Rows.Add(statusDataRow);
        myDataSet.Tables.Add(statusDataTable);

        returncodeDataRow["ReturnCode"] = dbCommand.Parameters["Return"].Value;
        returncodeDataTable.Rows.Add(returncodeDataRow);
        myDataSet.Tables.Add(returncodeDataTable);

        xmlReturnDoc.LoadXml(myDataSet.GetXml());

        return xmlReturnDoc;
    }
    // THIS IS WHERE I WANT MY RAISE ERROR TO GO
    catch (Exception e) 
    {
        return ReturnClientError(e, "someerror");
    }
}

Meu procedimento armazenado SQL:

CREATE PROCEDURE updateSomeItem
(
    @ItemIdNmb             INT,
    @Foo                   VARCHAR(100),
    @UpdateLoginIdNmb      INT
)

AS

SET NOCOUNT ON

/* If the user performing the action did not create the Item in question, 
    raise an error. */
IF NOT EXISTS
    (
    SELECT 1
    FROM Items
    WHERE IdNmb = @ItemIdNmb
        AND LoginIdNmb = @UpdateLoginIdNmb
    )
    RAISERROR (
        'User action not allowed - User is not the owner of the specified Item', 
        10, 
        1)

UPDATE Items
SET Foo = @Foo
WHERE IdNmb = @ItemIdNmb

RETURN 0

SET NOCOUNT OFF
GO
Foi útil?

Solução 2

Atualizei meu procedimento armazenado com o seguinte:

/* If the user performing the action did not create the Item in question, 
    return a code other than 0. */
IF NOT EXISTS
    (
    SELECT 1
    FROM Items
    WHERE IdNmb = @ItemIdNmb
        AND LoginIdNmb = @UpdateLoginIdNmb
    )
    RETURN 1

E eu lido com meu arquivo .asmx como este:

int returnValue = (int)dbCommand.Parameters["Return"].Value;

if (returnValue == 0)
    statusDataRow["Status"] = "Success";
/* Stored Procedure will return a value of "1" if the user is 
    attempting to update an Item that they do not own. */
else
    statusDataRow["Status"] = "Error";

statusDataTable.Rows.Add(statusDataRow);
myDataSet.Tables.Add(statusDataTable);

returncodeDataRow["ReturnCode"] = dbCommand.Parameters["Return"].Value;
returncodeDataTable.Rows.Add(returncodeDataRow);
myDataSet.Tables.Add(returncodeDataTable);

Outras dicas

O problema é que a gravidade do erro é muito baixa. As severidades 1 - 10 são tratadas como mensagens de informação e não quebram o fluxo de um aplicativo C#.

Uma explicação mais completa pode ser encontrada em um responda a partir de Remus Rusanu.

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