ehsan_kabiri_33
ehsan_kabiri_33

Reputation: 386

Pass complex object between action methods ASP.Net MVC Core

I studied most of the similar questions but couldn't find the answer! Let me declare that I can define a simple TempData like an string,int and get it in another action method successfully, but

I have 3 parameters/variable in ActionMethod1 which is named "ExternalLoginCallBack", and need to ask a "UserName" from user on client side and then save the total 4 parameters in ActionMethod2 which is named "CreateExternalUser". This is what I have. AskUserNameView_NoActionMethod.cshtml as below:

@model ExternalUserViewModel

<form asp-action="CreateExternalUser" asp-controller="Account" method="post">        
        <label asp-for="UserName">Input your UserName Here: </label>
        <input asp-for="UserName" >                      
        <input  type="submit" value="ُSubmit"/>
</form>

(Using TempData) Attemp-No.1:

public async Task<IActionResult> ActionMethod1

//some codes here

var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync();
TempData["externalLoginInfo"] = externalLoginInfo;
TempData["email"] = email;
TempData["returnUrl"] = returnUrl;

return View("AskUserNameView_NoActionMethod");

but instead of showing the AskUserNameView_NoActionMethod.cshtml it shows just a white page with no errors,no exception and nothing : enter image description here

Attemp-No2: I removed "ExternalLoginInfo" type and only two simple string as an object remained to pass to ActionMethod2:

public async Task<IActionResult> ActionMethod1

//some codes here


var externalUserViewModel= new ExternalUserViewModel()
{   
Email = email,
ReturnUrl = returnUrl,
};   

TempData["externalUserViewModel"] = externalUserViewModel;

return View("AskUserNameView_NoActionMethod");

but again the white page above appeared. When I remove the complex TempData, my AskUserNameView_NoActionMethod.cshtml rendered successfully, and I can pass UserName which is entered by client side, to ActionMethod2. But without 3 other parameters which is needed to create a new External user !!

My ExternalUserViewModel is as below:

 public class ExternalUserViewModel
{
    public ExternalLoginInfo ExternalLoginInfo { get; set; }
    public string Email { get; set; }

    public string UserName { get; set; }
    public string ReturnUrl { get; set; }
}

and already added these codes to startup.cs:

services.AddControllersWithViews();
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

app.UseSession();

If TempData is not apllicable, I tried to pass my model with 3 parameters (Email,ReturnUrl,ExternalLoginInfo ) to strongly typed AskUserNameView_NoActionMethod.cshtml, but again Username entered by client side,Email and returnedUrl passed to ActionMethod2 but externalLoginInfo was null .

Summary: need an example to pass a complex data/object from actionmethod1 to actionmethod2 , without redirect to actionmethod2 !!

Upvotes: 0

Views: 1146

Answers (1)

LouraQ
LouraQ

Reputation: 6881

You have two methods to achieve it.

As the TempData cannot store complex object here ,you can Serialize the object to json string and store it in TempData, then you can get the json string in CreateExternalUser action and Deserialize this json string to the correspond object as follow:

    public async Task<IActionResult> ActionMethod1()
    {

        //some codes here 
        var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync();
        TempData["externalLoginInfo"] = JsonConvert.SerializeObject(externalLoginInfo);
        TempData["email"] = email;
        TempData["returnUrl"] = returnUrl;

        return View("AskUserNameView_NoActionMethod");

    }

Receive:

public async Task<IActionResult> CreateExternalUser(UserName  userName)
        {
            //some codes here 
            var externalLoginInfo = JsonConvert.DeserializeObject<ExternalLoginInfo>(TempData["externalLoginInfo"].ToString());

           var email = TempData["email"] as string;
            var returnUrl = TempData["returnUrl"] as string;

            return View(); 
        }

Another method is to create a custom method named TempDataExtensions to pass object from an action to another.

public static class TempDataExtensions
{
    public static void Put<T>(this ITempDataDictionary tempData, string key, T value) where T : class
    {
        tempData[key] = JsonConvert.SerializeObject(value);
    }

    public static T Get<T>(this ITempDataDictionary tempData, string key) where T : class
    {
        object o;
        tempData.TryGetValue(key, out o);
        return o == null ? null : JsonConvert.DeserializeObject<T>((string)o);
    }
}

Store object:

var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync();
TempData.Put("externalLoginInfo", externalLoginInfo);

Get object:

var externalLoginInfo = TempData.Get<ExternalLoginInfo>("externalLoginInfo");

Upvotes: 2

Related Questions