简体   繁体   中英

Can you pass a SQL query string to Web API controller?

Im trying to build form that constructs a SQL query string depending on the users search preferences and then passes the query to an API controller that gets the data from a database.

[Route("api/SelectionHelper/RiskGridView/{query}")]
    [HttpGet]
    public HttpResponseMessage RiskGridView(string query)
    {


        try
        {
            using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Actor"].ConnectionString))
            {
                con.Open();


                using (SqlCommand cmd = new SqlCommand("SELECT * FROM Table WHERE key ='" + Constants.GlobalId + "'", con))
                {
                    DataTable dt = new DataTable();

                    SqlDataAdapter adp = new SqlDataAdapter(cmd);

                    adp.Fill(dt);


                    if (dt.Rows.Count == 0)
                    {
                        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "No active session found");
                    }
                    else
                    {

                        List<RiskSearch> list = new List<RiskSearch>();

                        cmd.CommandText = query;

                        SqlDataReader reader = cmd.ExecuteReader();

                        while (reader.Read())
                        {
                            list.Add(new RiskSearch()
                            {
                                QuoteRef = Convert.ToInt32(reader["ref"]),
                                PolicyRef = reader["reference"].ToString(),
                                Insured = reader["sap_ins_name"].ToString(),
                                QuoteStatus = reader["status"].ToString(),
                                Order = Convert.ToInt32(reader["recd"]),
                                InceptionDate = Convert.ToDateTime(reader["inception"]).ToShortDateString(),
                                PolicyType = reader["type"].ToString(),
                                Broker = reader["name"].ToString(),
                                QuoteStatusDate = Convert.ToDateTime(reader["date"]).ToShortDateString(),
                                RiskStatus = reader["status"].ToString()
                            });
                        }

                        return Request.CreateResponse(HttpStatusCode.OK, list);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
        }

    }
}

How the Query Gets built

         if (txt_ref.Text != "")
        {
            SearchString += "[table].[field]" + 
CreatedFunctions.fct_SQL_WhereSearchStringText(txt_ref.Text);
        }
        if (txt_reference.Text != "")
        {
            SearchString += "[Table].[Field]" + 
CreatedFunctions.fct_SQL_WhereSearchStringText(txt_reference.Text);
        }
        if (txtPolicyGroup.Text != "")
        {
            SearchString += "[Table].[Field]" + 
 CreatedFunctions.fct_SQL_WhereSearchStringText(txt_Group_ref.Text);
        }
        if (txt__name.Text != "")

I've tried passing the query as a string variable in the url but it throws a 404 or 400 error.

is this the correct way of doing it? Any advice would be greatly appreciated!

The only systems that should be passing SQL between layers are things that are inherently SQL tools (things like SEDE , for example).

In all other cases, you should almost certainly be passing some DTO between the layers that represents the available search options, for example

public HttpResponseMessage RiskGridView(string reference = null, string policyGroup = null, ... )

or via json with:

class SearchRequest {
    public string Reference {get;set;}
    public string PolicyGroup {get;set;}
    // ...
}

public HttpResponseMessage RiskGridView(SearchRequest query)

Now the RiskGridView method would build the required SQL, using parameters (not concatenation). The calling system should not need to know the table layout .

I would also strongly suggest tools like "Dapper" for actually executing it once constructed:

...
if(opt.Reference != null) sql.Append(" and x.Reference=@Reference");
if(opt.PolicyGroup != null) sql.Append(" and x.PolicyGroup=@PolicyGroup");
//...
var results = connection.Query<RiskSearch>(sql.ToString(), opt); // handles params/reader

or use a tool like LINQ:

IQueryable<RiskSearch> rows = ctx.RiskSearch;
if(opt.Reference != null) rows = rows.Where(x => x.Reference == opt.Reference);
if(opt.PolicyGroup != null) rows.Where(x => x.PolicyGroup == opt.PolicyGroup);
// ...
var results = rows.Take(count).ToList();

Pass the required information as query string variables. Then, sanity check them. Then use a stored procedure and pass them as parameter objects.

Even better would be to use an ORM like Entity Framework.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM