Rob
Rob

Reputation: 199

What's the most efficient way I can reference the same repeated code which I want to use in multiple actions?

I'm trying to make my controller actions more efficient. Let's say I have two actions, one a ViewResult and the other a PartialViewResult. Both perform the same action at a certain point which is returned in the same viewModel by both actions, let's say my two actions are:

public ViewResult datastream(string dataID)
{
    var data = db.data.FirstOrDefault(i -> i.ID == dataID);
    var viewModel = new DataViewModel();
    viewModel.Data = data.Data;
    return view(viewModel)
}

public PartialViewResult datastreampartial(string dataID)
{
    var data = db.data.FirstOrDefault(i -> i.ID == dataID);
    var viewModel = new DataViewModel();
    viewModel.Data = data.Data;
    return PartialView("_datapartial", viewModel)
}

I can put the following:

var data = db.data.FirstOrDefault(i -> i.ID == ID)

var viewModel = new DataViewModel();

viewModel.Data = data.Data;

code into another action and then RedirectToAction back to the original actions carrying the viewModel, I could then make those original two actions act in the appropriate way given whether the viewModel was null or not. This seems a bit of a farce though. Presumably there is some way I can easily reference this single chunk of code so it can be used in both actions easily and the viewModel returned by both actions.

What is the best way to do this?

Upvotes: 0

Views: 72

Answers (3)

Nahuel Ianni
Nahuel Ianni

Reputation: 3185

You can create a private method that returns the object being used by both your public methods:

public ViewResult datastream(string dataID)
{
    return view(this.GetDataViewModel(dataID));
}

public PartialViewResult datastreampartial(string dataID)
{
    return PartialView("_datapartial", this.GetDataViewModel(dataID))
}

private DataViewModel GetDataViewModel(string dataId)
{
    var data = db.data.FirstOrDefault(i => i.ID == dataID);
    var viewModel = new DataViewModel()
    {
        Data = data?.Data;
    }

    return viewModel;
}

Keep in mind that your code might throw an exception as you are trying to access data.Data without checking if it is a null value; not a problem in my private method.

Upvotes: 1

Fran
Fran

Reputation: 6530

Just create a private method on your controller and call that from your actions. There's not reason to call RedirectToAction

private WhateverYouTypeIs GetData(int Id)
{
    var data = db.data.FirstOrDefault(i -> i.ID == ID)

    var viewModel = new DataViewModel { Data = data.Data);

    return viewModel;
}

Then change your methods

public ViewResult datastream(string dataID)
{
    return view(GetData(dataID));
}

public PartialViewResult datastreampartial(string dataID)
{
    return PartialView("_datapartial", GetData(dataID));
}

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727067

Efficiency in terms of CPU cycles does not make much difference here, so you should go for the most readable approach that shares as much code as you can share.

Making a helper method that obtains DataViewModel based on ID is a classic approach, available in imperative languages:

private static DataViewModel GetViewModel(string dataID) {
    // You can flatten your three lines into one with {} initialization syntax
    return new DataViewModel {
        Data = db.data.FirstOrDefault(i -> i.ID == dataID)
    };
}

Now you can use your method in all your actions with a single line:

return view(GetViewModel(dataID))
...
return PartialView("_datapartial", GetViewModel(dataID))

Upvotes: 1

Related Questions