Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the same method to PUT and POST

Tags:

c#

wcf

I'm developing a WCF Rest Service and I have this on my ServiceContract:

    [OperationContract]
    [WebInvoke(Method = "POST",
        UriTemplate = "/users",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    User AddOrUpdateUser(User user);

    [OperationContract]
    [WebInvoke(Method = "PUT",
        UriTemplate = "/users",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    User AddOrUpdateUser(User user);

I'm going to use User AddOrUpdateUser(User user); to POST and PUT:

    public User AddOrUpdateUser(User user)
    {
        if (user == null)
            throw new ArgumentNullException("user", "AddOrUpdateUser: user is null");

        using (var context = new AdnLineContext())
        {
            context.Entry(user).State = user.UserId == 0 ?
                                        EntityState.Added :
                                        EntityState.Modified;
            context.SaveChanges();
        }

        return user;
    }

I'm following this pattern to do it.

But, I get an error:

The type 'MyCompanyWCFService.IMyCompanyService' already contains a definition for 
'AddOrUpdateUser' with the same parameters

How can I fix this problem?

like image 722
VansFannel Avatar asked May 29 '26 16:05

VansFannel


1 Answers

You cannot have two methods with the same signature - that's a C# issue, not a WCF one. You have basically two choices to go here. The first is to have two different methods, and have one call the other, or have a third method called by both):

public interface ITest
{
    [OperationContract]
    [WebInvoke(Method = "POST",
        UriTemplate = "/users",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    User AddUser(User user);

    [OperationContract]
    [WebInvoke(Method = "PUT",
        UriTemplate = "/users",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    User UpdateUser(User user);
}

And the implementation:

public class Service
{
    public User AddUser(User user) { return AddOrUpdateUser(user); }
    public User UpdateUser(User user) { return AddOrUpdateUser(user); }
    private User AddOrUpdateUser(User user)
    {
        if (user == null)
            throw new ArgumentNullException("user", "AddOrUpdateUser: user is null");

        using (var context = new AdnLineContext())
        {
            context.Entry(user).State = user.UserId == 0 ?
                                        EntityState.Added :
                                        EntityState.Modified;
            context.SaveChanges();
        }

        return user;
    }
}

Another alternative would be to have one single method which accepts multiple HTTP methods; you can do that by specifying Method = "*" on the WebInvoke attribute. But if you go that route you should validate, within the operation, that the incoming HTTP verb is one of those you expect:

public interface ITest
{
    [OperationContract]
    [WebInvoke(Method = "*",
        UriTemplate = "/users",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare)]
    User AddOrUpdateUser(User user);
}

And the implementation:

public class Service
{
    public User AddOrUpdateUser(User user)
    {
        var method = WebOperationContext.Current.IncomingRequest.Method.ToUpperInvariant();
        if (method != "POST" || method != "PUT")
        {
            throw new WebFaultException(HttpStatusCode.MethodNotAllowed);
        }

        if (user == null)
            throw new ArgumentNullException("user", "AddOrUpdateUser: user is null");

        using (var context = new AdnLineContext())
        {
            context.Entry(user).State = user.UserId == 0 ?
                                        EntityState.Added :
                                        EntityState.Modified;
            context.SaveChanges();
        }

        return user;
    }
}
like image 129
carlosfigueira Avatar answered May 31 '26 06:05

carlosfigueira



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!