Should I create two seperate Services and then combine them or have one large?
Overview of your service looks like this. I've put T-SQL commands that execute in each methods comment.

interface ICampaignService
{
    //INSERT = INSERT INTO CAMPAIGN....
    void InsertX( ... );

    //UPDATE = UPDATE CAMPAIGN....
    void UpdateX( ... );

    //DELETE = DELETE FROM CAMPAIGN
    void DeleteX( ... );

    //ALL = SELECT * FROM CAMPAIGN
    IList&lt;Campaign&gt; AllCampaigns();

    //FIND = SELECT * FROM CAMPAIGN WHERE ...
    //FILTER
    //GET
    Campaign FindX( ... );
    Campaign GetCampaignByID(object id);

    //SAVE = COMMIT TRANSACTION;
    void Save();
}


And you yourself say:


  I have two separate tables, Campaign and CampaignDetails. They relate via CampaignID.


The problem is your service is not just a thin layer over Entity Framework it still is a thin layer over SQL. In fact even your action names mirror database commands.

The service interface must be a must be the interface to your business logic layer. 
And repositories be your gateway to the data access layer.

Let's look at the Create(Campaign campaign) action for a second:

Create(Campaign campaign)
{
// BOILER PLATE IGNORED
    _campaignService.InsertCampaign(campaign);
    var campaignDetails = new CampaignDetails()
    {
        CampaignId = campaign.CampaignId
    };

    _campaignService.InsertCampaignDetails(campaignDetails);
    _campaignService.Save();
// BOILER PLATE IGNORED
}


When your user pressed the submit button one time, did he intend 4 different things?

Create(Campaign campaign)
{
// BOILER PLATE IGNORED
    _campaignService.CreateCampaign(campaign);
// BOILER PLATE IGNORED
}


It is clear that this more closely captures user's intent.

void CreateCampaign(Campaign campaign)
{
    _campaignRepository.InsertCampaign(campaign);
    var campaignDetails = new CampaignDetails()
    {
        CampaignId = campaign.CampaignId
    };

    _campaignRepository.InsertCampaignDetails(campaignDetails);
    _campaignRepository.Save();
}


As you do the above transformation -in other words above refactoring- for each action there will be unused methods on the service interface. Remove them and your service interface will be cleaner. 


  I want a service that can handle both at the same time, as they're closely related and when one gets updated- so will the other.


This means that Campaign and CampaignDetails form an aggregate. And Campaign is the aggregate root. (I'm just giving you the standard terminology, so you can more easily look up the situation on the Internet.)

In situation where you have closely related [entities] and [such that] when one gets updated- so will the other, or in database-speak a master table and one ore more detail tables, you service should not contain direct references to the detail entities, or in other words you service should only deal with the aggregate root, in this particular case Campaign. It only makes sense that ICampaignService only deals with Campaigns directly.

I had asked for the UpdateCampaignDetails example usage so that I can give a more concrete example of this but we will have to make do with the made up example below:

Suppose we are talking about sales campaigns here and one thing that is stored in CampaignDetails is a discount rate for the Campaign. After the above refactoring to your service and controller instead of UpdateCampaignDetails your service will have methods like below:

void ChangeDiscountRate(Campaign campaign, decimal newDiscountRate)


or

void ChangeDiscountRate(Guid CampaignId, decimal newDiscountRate)


whose implementation would be something like:

var campaignDetailsToUpdate = _campaignDetailsRepository.GetById(CampaignId);
campaignDetailsToUpdate.DiscountRate = newDiscountRate;
_campaignDetailsRepository.Update(campaignDetailsToUpdate);
_campaignDetailsRepository.Save();


You need not stop there. Ideally after a next round of refactorings (Including defining One-to-One and one-to-many relations where necessary) your service methods will read like below:

var campaignToUpdate = _campaignRepository.GetById(CampaignId);
campaignToUpdate.ChangeDiscountRate(newDiscountRate);
_campaignRepository.Update(campaignToUpdate );


or more generally:

var aggregateRoot = repository.GetById(id);
aggregateRoot.ModifyThisEntityAndItsDetails(...);
repository.Update(aggregateRoot);


The other thing to do would be separate the methods that update campaigns (hint those methods that return void, who are also the methods that are called from [HttpPost] controller methods from search methods (hint they are the method that return SomeCollection and take Expression&lt;Func&lt;Campaign, bool&gt;&gt; expression as parameters) that are called from elsewhere.