Request i Response za pomoca metody HttpWebRequest i HttpWebResponse

0

Witam napisałem metodę w której wykonuje postem chce wysłać link i otrzymać odpowiedź która jest w postaci xml-a. Chciałbym was zapytać czy poprawnie to zrobiłem

Wygląda to tak:
W obiekcie createOrderDto znajduje się String OrderLink. chce go wysłać z w odpowiedzi otrzymać xmla którego potem będę parsował. Czy to co napisałem jest poprawne? Może coś ominąłem...

private HttpWebResponse PlaceOrder (CreateOrderDto createOrderDto)
        {
            HttpWebRequest request = WebRequest.Create(createOrderDto.OrderLink) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "text/xml; encoding='utf-8'";
            if (request == null)
            {
                throw new NullReferenceException("request is not a http request");
            }
            return request.GetResponse() as HttpWebResponse;
        }
2

Sprawdzanie request == null po tym, jak dwa razy odwołujesz się do obiektu request to pomyłka. Sprawdzanie tego trzy linijki po tym, jak ten obiekt utworzyłeś to po prostu błąd.
Za to powinieneś zmienić rzutowanie z as T, które nie rzuca wyjątku jeśli obiektu nie da się castować na typ, na rzutowanie (T), które taki wyjątek rzuca.

0

zmieniłem trochę, ale niestety nie mam jak tego sprawdzić obawiam się że o czymś zapomniałem.

    private HttpWebResponse PlaceOrder (CreateOrderDto createOrderDto)
        {
            try {
                HttpWebRequest request = WebRequest.Create(createOrderDto.OrderLink) as HttpWebRequest;
                request.Method = "POST";
                request.ContentType = "text/xml; encoding='utf-8'";
                return request.GetResponse() as HttpWebResponse;
            }
            catch (Exception) { }
            {
                return null;
            }
        }
3

Podejście pierwsze:

private HttpWebResponse PlaceOrder(CreateOrderDto createOrderDto)
{
    var request = (HttpWebRequest)WebRequest.Create(createOrderDto.OrderLink);
    request.Method = "POST";
    request.ContentType = "text/xml; encoding='utf-8'";
    return (HttpWebResponse)request.GetResponse();
}

Ewentualny wyjątek złapie sobie klasa, która z metody PlaceOrder będzie korzystać.

Podejście drugie:

private HttpWebResponse PlaceOrder(CreateOrderDto createOrderDto)
{
    try
    {
        var request = (HttpWebRequest)WebRequest.Create(createOrderDto.OrderLink);
        request.Method = "POST";
        request.ContentType = "text/xml; encoding='utf-8'";
        return (HttpWebResponse)request.GetResponse();
    }
    catch (Exception ex)
    {
        logger.Error(ex);
        throw;
    }
}

Gdzie logger to jakiś logger dla Twojej klasy (np. nlog). Błąd zostaje zalogowany, ale wyjątek leci dalej, dzięki czemu metoda, która wywołała PlaceOrder jest świadoma tego, że coś się nie udało i w razie czego może się dowiedzieć co konkretnie poszło nie tak.

Podejście trzecie:

public class RequestFactory
{
    public HttpWebRequest GetRequest(string url)
    {
        var request = (HttpWebRequest)WebRequest.Create(createOrderDto.OrderLink);
        request.Method = "POST";
        request.ContentType = "text/xml; encoding='utf-8'";

        return request;
    }
}

// ...
// tu już Twoja klasa
// ...

private HttpWebResponse PlaceOrder(CreateOrderDto createOrderDto)
{
    try
    {
        var request = new RequestFactory().GetRequest(createOrderDto.OrderLink);
        return (HttpWebResponse)request.GetResponse();
    }
    catch (Exception ex)
    {
        logger.Error(ex);
        throw;
    }
}

Tutaj jeszcze masz zabezpieczenie przed DRY, czyli ciągłym powtarzaniem tworzenia obiektu requesta i przypisywaniem mu tych samych wartości. Ponadto literka S z SOLID (Single responsibility principle).

Czwarte podejście:

public interface IRequestFactory
{
    HttpWebRequest GetRequest(string url);
}


public class RequestFactory : IRequestFactory
{
    public HttpWebRequest GetRequest(string url)
    {
        var request = (HttpWebRequest)WebRequest.Create(createOrderDto.OrderLink);
        request.Method = "POST";
        request.ContentType = "text/xml; encoding='utf-8'";

        return request;
    }
}


public class YourClass
{
    private IRequestFactory requestFactory;


    public YourClass(requestFactory : IRequestFactory)
    {
        this.requestFactory = requestFactory;
    }

// ...

    private HttpWebResponse PlaceOrder(CreateOrderDto createOrderDto)
    {
        try
        {
            var request = requestFactory.GetRequest(createOrderDto.OrderLink);
            var response = request.GetResponse();
            return (HttpWebResponse)response;
        }
        catch (Exception ex)
        {
            logger.Error(ex);
            throw;
        }
    }
}

Tutaj użyjesz jakiegoś kontenera IoC (np. StructureMap) i masz kolejne literki z SOLID.

Kolejna wersja, bazująca na tej ostatniej, żeby nie powtarzać się.

// gdzieś w innym pliku:
public class PlaceOrderModel
{
    public string OrderLink { get; set; }
}

public class PlaceOrderResult
{
    public PlaceOrderResult(HttpWebResponse response)
    {
        // tutaj parsowanie odpowiedzi z serwera, robione za pomocą kolejnych klas (DRY! SOLID! KISS!)
    }
}


// Twoja klasa
    private PlaceOrderResult CreateOrder(PlaceOrderModel model)
    {
        try
        {
            var request = requestFactory.GetRequest(PlaceOrderModel.OrderLink);
            var response = new PlaceOrderResult((HttpWebResponse)request.GetResponse());
            return response;
        }
        catch (Exception ex)
        {
            logger.Error(ex);
            throw;
        }
    }

Tutaj masz wszystko opakowane w odpowiednie modele, dzięki czemu metody używające CreateOrder nie muszą same parsować odpowiedzi serwera.

Można tak dalej, ale już mi się nie chce.

0

Super, dzięki. Co do działania to jeszcze muszę nad tym popracować.

1 użytkowników online, w tym zalogowanych: 0, gości: 1