Create a Web Api that calls another Web Api

1

I created an Api Web here in my work to be consumed by my Xamarin Forms project. 100% running smoothly ... Then I was informed that in fact here is used 2 web api's for security. That is, I will have to create a web-based Api ("frontend") with external access, which would function as a doorman, passing the calls to another Web Api ("backend") and this one only has access to DB and only accepts internally . As I'm a beginner and I took a beating to get this Web Api to work and it works, I'd like some help on how to do this. I would have to call the WebApi 1 and it will carry the values entered by the user up to the Web Api 2 ... this in turn will have the database calls and all the controllers ... after the query is that I did not understand the what to do, because the data is spit on Json and a good part I was able to make it work in the search.

My code in Xamarin:

ApiCall apiCall = new ApiCall();

                apiCall.GetResponse<List<Envolvido>>("nomes", "Envolvidos", nomepesquisa, nomemae, nomepai, dtnasc, nrg, ncpf).ContinueWith(t =>
               {
                   //Aqui verificamos se houve problema ne requisição
                   if (t.IsFaulted)
                   {
                       Debug.WriteLine(t.Exception.Message);
                       Device.BeginInvokeOnMainThread(() =>
                       {
                           DisplayAlert("Falha", "Ocorreu um erro na Requisição :(", "Ok");
                           //IsBusy = false;
                       });
                   }
                   //Aqui verificamos se a requisição foi cancelada por algum Motivo
                   else if (t.IsCanceled)
                   {
                       Debug.WriteLine("Requisição cancelada");

                       Device.BeginInvokeOnMainThread(() =>
                       {
                           DisplayAlert("Cancela", "Requisição Cancelada :O", "Ok");
                           //IsBusy = false;

                       });
                   }

                   //Caso a requisição ocorra sem problemas, cairemos aqui
                   else
                   {
                       //Se Chegarmos aqui, está tudo ok, agora itemos tratar nossa Lista
                       //Aqui Usaremos a Thread Principal, ou seja, a que possui as references da UI
                       Device.BeginInvokeOnMainThread(() =>
                          {
                              //IsBusy = false;
                              ListaDados.ItemsSource = t.Result;
                              var count = ListaDados.ItemsSource.OfType<object>().Count();
                              if (count == 0)
                              {
                                  DisplayAlert("Cancela", "Não há dados retornados.", "Ok");
                              }
                              else
                                  Navigation.PushAsync(new ResultadosBuscados(ListaDados.ItemsSource));
                          });

                   }

part of my ApiCall that calls the Api Web:

public class ApiCall
    {
        static readonly string ApiUrl = "http://Localhost:1762/api/{0}/{1}?nomePesquisa={2}&nomeMae={3}&nomePai={4}&dtNasc={5}&nrg={6}&ncpf={7}";

            public async Task<T> GetResponse<T>(string controller, string method, string nomepesquisa, 
            string nomemae, string nomepai, string dtnasc, string nrg, string ncpf) where T : class
        {
            var client = new System.Net.Http.HttpClient();


            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


            var urllink = string.Format(ApiUrl, controller, method, nomepesquisa, nomemae, nomepai, dtnasc, nrg, ncpf);
            var response = await client.GetAsync(urllink);

            //Lê a string retornada
            var JsonResult = response.Content.ReadAsStringAsync().Result;

            if (typeof(T) == typeof(string))
                return null;

            //Converte o resultado Json para uma Classe utilizando as Libs do Newtonsoft.Json
            var rootobject = JsonConvert.DeserializeObject<T>(JsonResult);
            return rootobject;
        }
}

My controller code in Api Web:

[RoutePrefix("api/nomes")]
    public class NomesController : ApiController
    {
        public string GetConnectionString()
        {
            string MeuConnString = "Data Source=(DESCRIPTION ="
                + "(ADDRESS=(PROTOCOL = TCP)(HOST = xxx)(PORT = xxx))"
                + "(CONNECT_DATA = (SERVER = DEDICATED)(service_name = xxx)));"
                + "User Id = xxx; Password=xxx";
            return MeuConnString;
        }


        [HttpGet]
        [Route("Envolvidos")]
        public IEnumerable<Envolvido> GetEnvolv(string nomePesquisa, string nomeMae, string nomePai, string dtnasc
            , string nRG, string nCPF)
        {

            DataSet lretorno = new DataSet();

            string connectionString = GetConnectionString();
            using (OracleConnection connection = new OracleConnection())
            {
                connection.ConnectionString = connectionString;

                OracleDataReader reader = null;
                OracleCommand cmd = new OracleCommand();
                cmd.Connection = connection;
                cmd = new OracleCommand("MOBILE.XAPIMAND.BUSCAPOSCANDIDOSPF", connection);
                cmd.CommandType = CommandType.StoredProcedure;

                //variáveis entrada            
                cmd.Parameters.Add(new OracleParameter("ivnome",nomePesquisa));
                cmd.Parameters.Add(new OracleParameter("ivmae", nomeMae));
                cmd.Parameters.Add(new OracleParameter("ivpai", nomePai));
                cmd.Parameters.Add(new OracleParameter("ivdatanasc", dtnasc));
                cmd.Parameters.Add(new OracleParameter("ivrg", nRG));
                cmd.Parameters.Add(new OracleParameter("icpf", nCPF));
                //variáveis de saida          
                cmd.Parameters.Add(new OracleParameter("oretorno", OracleDbType.RefCursor)).Direction = ParameterDirection.Output;
                cmd.Parameters.Add(new OracleParameter("qretorno", OracleDbType.RefCursor)).Direction = ParameterDirection.Output;

                connection.Open();
                cmd.ExecuteNonQuery();

                reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);

                //CRIO A LISTA
                lretorno.Load(reader, LoadOption.OverwriteChanges, "BUSCAPOSSIVEISCANDIDATOSPF");
                connection.Close();
                connection.Dispose();


                //CARREGO O DATASET E TRANSFORMO PARA IENUMERABLE E RETORNO SEUS VALORES PRO JSON
                return lretorno.Tables[0].AsEnumerable().Select(row => new Envolvido
                {
                    SUSPID = Convert.ToInt32(row["SUSPID"]),
                    IVNOME = Convert.ToString(row["SUSPNOME"]),
                    IVMAE = Convert.ToString(row["SUSPMAE"]),
                    IVPAI = Convert.ToString(row["SUSPPAI"]),
                    IVDATANASC = Convert.ToString(row["SUSPDATANASC"]).Replace(" 00:00:00", ""),
                    IVRG = Convert.ToString(row["RG"]),
                    ICPF = Convert.ToString(row["CPF"]),
                    MANDADO = Convert.ToInt16(row["TEMMANDADO"]),
                    OCORRENCIA = Convert.ToInt16(row["TEMOCORRENCIA"]),

                });


            }
        }

    }
    
asked by anonymous 19.07.2016 / 21:37

1 answer

2

First of all,% s of% s is not as secure as just one, this approach will not protect your system from attack, such as WebAPI , MITM or whatever other attack you may imagine.

If your fear is that any serious flaw will control the server with Sql Injection to some hacker, in this case it will have full access to the machine and its network, so it could access its entire structure

Now we go to the other problem, WebAPI 1 , all accesses in the second Session will be carried out by the same user, then it will not have a WebAPI per user and will have to use a Session use workaround and add Cache as SessionID on all requests).

We still have a second, somewhat more serious problem, Authentication and Authorization, as your second Header will know if the user who made the request the first WebAPI has access. In short you will not be able to use WebAPI and you will have to implement your own solution.

Another problem involves transactions, let's say a ASP.NET Identity request needs to make two distinct calls to WebAPI 1 , how will you rollback the first one if the second one goes wrong? a WebAPI 2 is missing right?

But still, a multilayered system still has its purpose, it may be that I want to make a presentation layer using TransactionScope , and other systems that need to consume this service and some of them can not make a request AngularJS + WebAPI .

In this case you will need a WCF service that offers one or more% of% s that are appropriate for the applications that are consuming the same. the http that provides more security for communication between two applications made in binding is binding ... here is an example: Peer-to-Peer Programming with WCF and .NET Framework 3.5 .

Remembering that a service with .NET allows you to pass a transaction to it, then you can create NetPeerTcpBinding in WCF , make n calls to TransactionScope and make a WebAPI safely if necessary .

And to consume a WCF service, you only have to add serviço , rollback will have all the work of creating the Service Reference classes, control opening channels, sending messages, etc ...

Now you can ask me why not use Visual Studio in proxy and use webHttpBinding as interface for WCF ? the first point is the competition, the WebAPI can manage much better a scenario with multiple connections, the other point is the configuration options, you will have a larger range with Web .

    
20.07.2016 / 18:52