1

I need help regarding below:

I am trying to design an API. For creating contracts below are the two approaches:

Approach 1:

public class MyController
{
  public void MyAction1(Dictionary<string, dynamic> input)
  {
    //Use input like below
    //Read from input dictionary and apply minimal business logic if needed
    //And Call CustomDataProvider library with input object itself(DataProvider designed in such a way that it takes Dictionary and used values as procedure input. Dictionary key is same as procedure arguments.)
  }

public void MyAction2(Dictionary<string, dynamic> input)
  {
    //Use input like below
    //Read from input dictionary and apply minimal business logic if needed
    //And Call CustomDataProvider library with input object itself(DataProvider designed in such a way that it takes Dictionary and used values as procedure input. Dictionary key is same as procedure arguments.)
  }
}

In this case we don't need data contract at all.


Approach 2:

public class MyController
{
  public void MyAction1(MyContractBusinessObject1 input)
  {
    //Do normal business logic processing using input object and call DBProvider by creating a dictionary from business object
  }


public void MyAction2(MyContractBusinessObject2 input)
  {
    //Do normal business logic processing using input object and call DBProvider by creating a dictionary from business object
  }
}

In this case we'll have different business classes as contract for different action inputs. Can you please suggest which of the above approaches is better and why?

Let me give an example. Suppose My actions are doing login and new account creation. In first case input will be

new Dictionary<string, dynamic>{{"Name","myname"},{"Passowrd",'mypassword'}}

and

new Dictionary<string, dynamic>{{"Name","myname"},{"Passowrd",'mypassword'},{"Age",myage},{"otherInfo",myotherinfo}}

but in approach 2 input will be

 class Login{
    public string Name{get; set;}
    public string Password{get; set;}
} 

and

class NewAccount{
public string Name{get; set;}
public string Password{get; set;}
public int Age{get; set;}
public OtherInfo OtherInfo{get; set;}
}
  • What exactly is the data that you need to pass to the actions? What are the definitions of MyContractBusinessObject*? – Thomas Stringer Jun 18 '15 at 16:54
  • That completely depends on the business requirement by that actions. I have updated the question with an example. Please refer the question. – ATP Jun 18 '15 at 17:07
  • What is the purpose of the extra data that'll be passed in? Is it just optional data that can sometimes be there and sometimes not? Is it to be ignored? – Shelby115 Jun 18 '15 at 18:18
  • please don't cross-post: stackoverflow.com/questions/30921193/… – gnat Jun 18 '15 at 19:10
2

I'm going to go ahead an assume a few things here:

  • You're looking for a pattern to apply to multiple controllers
  • You have situations where a single action call can have varying amounts of data submitted (Name/Password guaranteed but sometimes age and other info are included).

If my assumptions are correct then I would suggest something to the following.

public class Contact
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
}

public class SpecialContact : Contact
{
    public String Title { get; set; }
}

public class AnotherSpecialContact : Contact
{
    public String Phone { get; set; }
}

public class ContactController
{
    public void MyAction(Contact contact)
    {
        // VALIDATE: Example validation provided.
        if (String.IsNullOrWhiteSpace(contact.FirstName)) { return; }
        if (String.IsNullOrWhiteSpace(contact.LastName)) { return; }

        if (contact is SpecialContact)
        {
            SpecialContact specialContact = contact as SpecialContact;
            // Do things SpecialContact specific.
        }
        else if (contact is AnotherSpecialContact)
        {
            AnotherSpecialContact anotherSpecialContact = contact as AnotherSpecialContact;
            // Do things AnotherSpecialContact specific.
        }

        // Do things Contact specific.
    }
}

Reasons for my suggestion:

  • You, as the API developer, know that the data you require is there and can do simple validation to make sure. If it was a dictionary or dynamic type then you'd have to do the type validation on top of regular validation.
  • As you can see from the SpecialContact and AnotherSpecialContact examples you can extend the action to handle special conditions where extra data is present. If you have situations where less data is present then that means you have the wrong base-class (i.e. Contact in this scenario).
  • (Sort of a repeat of #1 but...) You're using a statically typed language so why go against that with dynamic? The only time I've found dynamic particularly helpful is in cases of Reflection, any other time I've found it is the same or more work as the alternatives. If you think you need dynamic, give Object a try first.
  • In the above example no fields are going to be repeated in most of the cases. I have put field names just for example. If there are common fields across the contracts then your approach seems pretty good but could you please suggest for the non-repeating field scenario. – ATP Jun 22 '15 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.