Executing Query via C# MVC API - c#

I'm having trouble with some code, and I just can't seem to figure this out. I am attempting to send some data to a backend API that connects to our SQL Server and executes a query that I don't expect any kind of results from. The problem I'm having is that the SQL command isn't being sent to the server, and I'm getting a "404 - This file doesn't exist".
Here is the front part of the request:
public async Task ExportNewLists (string pid, string list)
{
var endpointUrl = string.Concat(baseEndpoint, "ExportLists", "/", pid, "/", list);
AddAuthorization();
using (HttpResponseMessage response = await client.GetAsync(endpointUrl))
{
if (!response.IsSuccessStatusCode)
{
Response.StatusCode = (int)response.StatusCode;
var result = response.Content.ReadAsStringAsync().Result;
var message = JsonConvert.DeserializeObject<ResponseError>(result);
}
}
}
And here is the API function I'm trying to call:
[Route("api/Lists/ExportLists/{pid}/{list}")]
[HttpGet]
[ResponseType(typeof(void))]
private async Task<IHttpActionResult> ExportList(string pid, string list)
{
using (var connection = db.Database.Connection)
{
try
{
connection.Open();
var command = connection.CreateCommand();
command.Connection = connection;
command.CommandText = "EXEC LIST_EXPORT_SINGLE";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#PID");
command.Parameters["#PID"].Value = pid;
command.Parameters.Add("#LIST");
command.Parameters["#LIST"].Value = list;
await command.ExecuteNonQueryAsync();
connection.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return Ok();
}

You have marked ExportScrubList as private. You cannot call an action marked as private via http.

Related

C# script to load data into SQL Server database doesn't work as expected

I am trying to query the APIs and insert the responses from it in to the SQL Server table using the script task. The script task is behaving in consistent that one time loads the data the other time the execution shows succeeded there is no data in the table.
Here is the C# code I am using to load the data:
public void Main()
{
// TODO: Add your code here
executeInsert();
}
public async void executeInsert()
{
try
{
var sqlConn = new System.Data.SqlClient.SqlConnection();
ConnectionManager cm = Dts.Connections["SurplusMouse_ADONET"];
string serviceUrl = Dts.Variables["$Project::RM_ServiceUrl"].Value.ToString();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(serviceUrl);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string APIUrl = string.Format(serviceUrl + "/gonogo");
var response = await client.GetAsync(APIUrl);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
try
{
sqlConn = (System.Data.SqlClient.SqlConnection)cm.AcquireConnection(Dts.Transaction);
const string query = #"INSERT INTO [dbo].[RM_Approved_Room_State]
(APPROVED_ROOM_STATEID,SOURCE_ROOMID,DEST_ROOMID,ENTITY_TYPEID)
SELECT id, sourceRoomRefId, destinationRoomRefId,entityRefId
FROM OPENJSON(#json)
WITH (
id int,
sourceRoomRefId int,
destinationRoomRefId int,
entityRefId int
) j;";
using (var sqlCmd = new System.Data.SqlClient.SqlCommand(query, sqlConn))
{
sqlCmd.Parameters.Add("#json", SqlDbType.NVarChar, -1).Value = result;
await sqlCmd.ExecuteNonQueryAsync();
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
finally
{
if (sqlConn != null)
cm.ReleaseConnection(sqlConn);
}
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
Can anyone help me how this script shows succeeded no data loaded but other time it loads. I am kind of stuck any help is greatly appreciated
Seems you have async calls inside your method, so it should be a Task
Try this way:
public void Main()
{
// TODO: Add your code here
executeInsert().GetAwaiter().GetResult();
}
public async Task executeInsert()
{
....
The calling method should also be async in order to await the result. In this case I guess you are doing a simple test on a console application

ASP MVC Core 3x Async database call - What am I not getting?

I am hoping someone can bring the light here because I am bouncing between one exception and another in VS and I am getting really fed up. I have read articles on how to perform async calls and seen code examples, yet for some reason I am somehow just not getting it according to VS.
I have a simple POCO, GetCompaniesResponse which will contain a collection of companies or errors depending on what happens:
public class GetCompanyResponse
{
public List<Company> Companies { get; set; }
public List<ErrorResult> Errors { get; set; }
public GetCompanyResponse()
{
Companies = new List<Company>();
Errors = new List<ErrorResult>();
}
}
All I am trying to do is convert a synchronous call that loads the companies from a database into an async call in order to free up the UI, whilst the data loads.
Here is the method I have converted:
public async Task<GetCompanyResponse> GetCompaniesByQuery()
{
var response = new GetCompanyResponse();
try
{
using (var conn = new SqlConnection(_configuration["Settings:DBConn"]))
{
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT TOP (1000) company_id, company_name, postcode FROM dbo.tbl_companies";
conn.Open();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
response.Companies.Add(new Company
{
CompanyId = Convert.ToInt32(reader["company_id"]),
CompanyName = reader["company_name"].ToString(),
PostCode = reader["postcode"].ToString()
});
}
}
}
catch (Exception e)
{
response.Errors.Add(new ErrorResult
{
ErrorMessage = e.Message
});
}
return response;
}
And my controller action is:
public async Task<IActionResult> ByQuery()
{
var service = new TestService(_configuration);
var response = await service.GetCompaniesByQuery();
return View(response);
}
The above method in VS simply keeps telling me I cannot return response because it cannot be converted. What am I doing wrong?
Severity Code Description Project File Line Suppression State
Error CS0029 Cannot implicitly convert type 'TestApp.Models.GetCompanyResponse' to 'System.Threading.Tasks.Task<TestApp.Models.GetCompanyResponse>' TestApp C:\Working Copies\TestApp\TestApp\Services\TestService.cs 59 Active
If I then try to extract the element of the task that strictly deals with the Companies property of the response POCO like so:
public async Task<IActionResult> ByQuery()
{
var service = new TestService(_configuration);
var response = new GetCompanyResponse();
response.Companies = (await service.GetCompaniesByQuery()).ToList();
return View(response);
}
public async Task<IEnumerable<Company>> GetCompaniesByQuery()
{
var response = new List<Company>();
try
{
using (var conn = new SqlConnection(_configuration["Settings:DBConn"]))
{
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT TOP (1000) company_id, company_name, postcode FROM dbo.tbl_companies";
conn.Open();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
response.Add(new Company
{
CompanyId = Convert.ToInt32(reader["company_id"]),
CompanyName = reader["company_name"].ToString(),
PostCode = reader["postcode"].ToString()
});
}
}
}
catch (Exception e)
{
//not implemented yet
}
await Task.WhenAll((IEnumerable<Task>)response);
return response;
}
Whilst VS stops complaining about it, I then start running into invalid cast errors when the code is ran.
InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List`1[TestApp.Models.Company]' to type 'System.Collections.Generic.IEnumerable`1[System.Threading.Tasks.Task]'.
TestApp.Services.TestService.GetCompaniesByQuery() in TestService.cs
+
await Task.WhenAll((IEnumerable<Task>)response);
TestApp.Controllers.HomeController.ByQuery() in HomeController.cs
+
response.Companies = (await service.GetCompaniesByQuery()).ToList();
It makes no sense to me why this is the cause when the examples I have seen do exactly the same thing as above. What am I failing to comprehend here?

Asynchronous method does not return control to its caller

I have created a supposed to be asynchronous method. And inside of that it has several await statements.
I am calling this method (in another class) from the main method.
But it doesn't return the control back to the caller (main), to execute the next statement (to get more data),
even though the operation takes long time to complete.
What is wrong here?
Could it be something with the return statement? Or do I need to wrap the logic inside a Task?
internal async static Task<List<Cars>> GetCarsAsync()
{
var cars = new List<Cars>();
try
{
using (var connection = new OracleConnection(ConfigurationManager.ConnectionStrings["KWC"].ConnectionString))
{
await connection.OpenAsync(); //first await
logger.Info("Opened database connection.");
StringBuilder selectStatement = new StringBuilder(Properties.Settings.Default.SelectCarsView);
using (var command = connection.CreateCommand())
{
command.CommandText = selectStatement.ToString();
logger.Info("About to execute following query on database: {0}", command.CommandText);
using (var reader = await command.ExecuteReaderAsync()) //second await
{
logger.Info("Executed query: {0}", command.CommandText);
while (await reader.ReadAsync()) //third await
{
var car = new Car { model = reader.GetString(0) };
//more code
cars.Add(car);
}
}
}
}
return cars;
}
catch (OracleException ex)
{
logger.Fatal(ex.Message);
throw;
}
}
static async Task Main(string[] args)
{
var getCarsTask = CarsManager.GetCarsAsync();
var getSomethingElseTask = DummyManager.GetMoreDataAsync();
// more similar tasks
var cars = await getCarsTask;
var moreData = await getSomethingElseTask;
// more code
}

POST Data To ASP.NET API With Xamarin

I am using C# asp.net and attempting to create my first Xamarin app. I have altered my asp.net API to hold the below syntax
private SqlConnection con;
private SqlCommand com;
private void connection()
{
string constr = ConfigurationManager.ConnectionStrings["getconn"].ToString();
con = new SqlConnection(constr);
}
[HttpPost]
public string AddUser(User user)
{
connection();
com = new SqlCommand("InsertData", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#FName", user.FName);
com.Parameters.AddWithValue("#Lname", user.LName);
com.Parameters.AddWithValue("#Phone", user.Phone);
com.Parameters.AddWithValue("#Compnay", user.Company);
com.Parameters.AddWithValue("#Email", user.Email);
com.Parameters.AddWithValue("#Pass", user.Pass);
com.Parameters.AddWithValue("#Registrationdate", user.Registrationdate);
con.Open();
int i = com.ExecuteNonQuery();
con.Close();
if (i >= 1)
{
return "New User Added Successfully";
}
else
{
return "Failed to Add User";
}
}
[HttpGet]
public string Get()
{
return "";
}
And I Have in my Xamarin syntax the below
void OnRegisterTap(object sender, EventArgs e)
{
InsertUser().ConfigureAwait(true);
}
private async Task InsertUser()
{
try
{
var httpClient = new HttpClient();
var url = "http://XXX.XXX.X.XXX:8888/api/user/adduser";
var data = new
{
FName = fname.Text,
LName = lname.Text,
Company = company.Text,
Email = Email.Text,
Pass = Password.Text,
Registrationdate = DateTime.UtcNow.ToString()
};
var jsonData = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var result = await httpClient.PostAsync(url, jsonData);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Now there is no error thrown when I press the button from my Xamarin app, I have verified that all the variables holds the appropriate values, however my issue is that no data is actually input into the database.
What step did I miss or did I improperly code that is keeping the data from being inserted?
Try changing
var result = await client.PostAsync(url, jsonData);
To
var response = await client.PostAsync(url, jsonData);
var result = await response.Content.ReadAsStringAsync();
Add FromBody to your controller (assuming User class is correct)
[HttpPost]
public string AddUser([FromBody] User user)
Use fiddler to Watch your request & response also your controller should return a proper HTTP response.

Propagate error back to user in ASP.net

I'm trying to propagate an error back to the user if their input is wrong.
Here's the code that should throw the error:
var sql2 = "select COD_id from COD_Codes where COD_name = #Value and COD_COT_id = #codeId";
SqlCommand cmd2 = new SqlCommand();
cmd2.CommandText = sql2;
cmd2.Parameters.AddWithValue("#Value", value);
cmd2.Parameters.AddWithValue("#codeId", result);
cmd2.Connection = connection;
cmd2.Transaction = transaction;
var code = Convert.ToInt32(cmd2.ExecuteScalar());
if (code == 0)
{
throw new ApplicationException(string.Format(#"({0}) is not a valid data for this credit report. Please check with your sys admin if this is a new data value", code));
}
return code;
This code is a few levels below my controller which looks like this:
[HttpPost]
public HttpResponseMessage SaveCreditReport(GrowData growData)
{
using (SqlConnection connection = CreateSqlConnection())
{
using (var transaction = connection.BeginTransaction())
{
try
{
var service = CreateCreditService(connection, transaction);
var user = GetUser(service);
if (log.IsInfoEnabled)
log.InfoFormat("Save credit report called by user '{0}' ",
user.UserName);
var growValues = growData.GrowRows.Select(growRow => new GrowValue() { Mnemonic = growRow.Mnemonic, Time = growRow.Time, Value = growRow.Value }).ToList();
var growCompValues = growData.GrowCompRows.Select(compRow => new GrowCompRowValue() { Mnemonic = compRow.Mnemonic, Value = compRow.Value }).ToList();
var reportId = service.SaveGrowCreditData(user.Id, growData.CompanyId, growValues, growCompValues, growData.Publish);
var message = this.Request.CreateResponse<int?>(HttpStatusCode.OK, reportId);
transaction.Commit();
return message;
}
catch
{
transaction.Rollback();
throw;
}
}
}
}
I'm not sure how and what kind of exception I need to throw to propagate the error back to user level. I don't want the standard "500 internal server error" message but instead the one that I've formatted in the code.
Can I just throw a new httpresponseexception instead of ApplicationException directly from the code? Will it then propagate back to controller level and unto the user?
In your catch method use CreateErrorResponse to create a response with whatever HttpStatusCode is appropriate:
catch (ApplicationException ex)
{
transaction.Rollback();
return this.Request.CreateErrorResponse(HttpStatusCode.NotAcceptable, ex);
}
A caveat from the documentation:
The request must be associated with an HttpConfiguration instance. An HttpResponseMessage whose content is a serialized representation of an HttpError instance [is returned]

Categories

Resources