2

I send from controller to view a list of objects, viewmodel is the object with some properties and pagedList, that need to be presented on page. And by pressing the button, this list need to be exported as file, that is, it need to go back to the controller and be processed there.

Model:

public class ProductsList : ListViewModel<Product>
{
     public ProductsList(string prefix) : base(prefix){ }

     public ProductsList(PagedList<Product> products)
     {
         List = products;
     }
     
     public int? ProductTypeFilter {get;set; }

     public string ProductTypeFilterName {get; set;}

     public string FilterBy { get; set; }
} 

ListViewModel just contain PagedList.

My controller

[HttpPost]
public FileResult SaveAsFile(PagedList<Product> viewmodel)
{
     ...
}

And my view

@model MyProject.ViewModels.ProductsList

if (Model.List.Count > 0)
    {
        <table id="products_table">
            <colgroup>
                <col class="productType"/>
            </colgroup>
            <thead>
            <tr>
                <th >
                    Product type
                </th>
            </tr>
            </thead>
            <tbody>
            @{ var i = 0; }
            @foreach (var item in Model.List)
            {
                <tr>
                    <td onclick="window.location='@Url.Action("Details", new {id = item.Id})'">
                        <p>
                            @item.Type
                        </p>
                    </td>
                    }
                </tr>
                i++;
            }
        </tbody>
        </table>
}

<form asp-action="SaveAsFile" enctype="multipart/form-data" method="post">
   @Html.HiddenFor(m => list);
   <input type="submit" value="Save as File"/>
</form>

I already have tried add to controller params tags [FromForm], [FromBody] (actually all available tags).

In view tried with hidden field in form, without it just with submit; put form on partial view; other forms: ajax, Html.ActionLink("Save as File", "SaveAsFile", new {Model}).

On debug mod Model.List has 21 items (but it can has more, like 2000 items), but when I press the button, viewmodel is creating newly.

Problem: viewmodel is creating newly and i cannot get back my full viewmodel to controller

I will be grateful for any help :)

Nick
  • 21
  • 4
  • If the collection comes from a database/storage you could request them again from that storage. – lordvlad30 Apr 26 '22 at 07:59
  • @lordvlad30 , Yes, but I have certain fields for sorting and filtering the list, which will not be added in this case – Nick Apr 26 '22 at 13:06
  • What is your `list` here in `@Html.HiddenFor(m => list);` list here? You cannot post the complex model by using single input. You need set input for each property in model. – Rena Apr 27 '22 at 06:05
  • @Rena , yeah, I tried to set `m.List`, a paged list from my viewmodel. Well, how another way i can return that list to controller? – Nick Apr 27 '22 at 08:32

1 Answers1

1

You can set your ViewModel data in a Session variable when you send the data to your View from Controller method:

In order to setup your Session, you can follow this S.O answer

Once your Session is setup, then you can put your ViewModel in it like:

HttpContext.Session.SetObjectAsJson("ProductsList", productslist);

And then retrieve it in your POST method like this:

[HttpPost]
public FileResult SaveAsFile(PagedList<Product> viewmodel)
{
     //Get your viewmodel here
     var list = HttpContext.Session.GetObjectFromJson<ProductsList>("ProductsList");
}

You can also serialize your ViewModel and then send it your Controller method without using form:

Create an ActionLink:

@Html.ActionLink("Submit", "SaveAsFile", "Home",  new { jsonModel= Json.Encode(Model.list) }, null)

And your Controller method:

public FileResult SaveAsFile(string jsonModel)
{
     var serializer= new DataContractJsonSerializer(typeof(Model.Product));
     var yourmodel=  (Product)serializer.ReadObject(GenerateStreamFromString(jsonModel));
}
Rahul Sharma
  • 7,768
  • 2
  • 28
  • 54
  • Thank you for reply, but there may be many such objects. After researching your method, I understand that there may be some problems with performance. – Nick Apr 26 '22 at 13:03
  • @Nick You could store the last filters that you applied and then retrieve the database from the `id` and the filters that you stored in your `Session`. – Rahul Sharma Apr 26 '22 at 16:12
  • yes, I thought the same, but I have a number of such pages with different filters and some ways to build this page like Index and search by some fields. And if I keep all the identifiers straight, there will be too many requests to the database. That's why I ask how to get viewmodel back to controller. – Nick Apr 27 '22 at 08:37
  • @Nick Can you try doing it through a `ActionLink`? – Rahul Sharma Apr 27 '22 at 18:55
  • Yep, I tried, same result – Nick May 01 '22 at 18:42