Blazor hybrid binding to expando objects

Oscar Lauroba 1 Reputation point
2022-09-19T11:27:11.17+00:00

I'm taking my first steps in Blazor hybrid apps and it seems it's not possible binding html inputs to expando object's properties. Expando objects are .Net. I'm also interesting in creating forms at runtime because my app does not know the data at development time but at runtime with dynamic objects like expandoObjects. Is there a way to accomplish this. If not, is there any preview in the future, .Net 7 maybe? Thank you very much.

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,373 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 54,626 Reputation points
    2022-09-19T15:28:25.33+00:00

    Expando objects are part of the dynamic runtime added for the IronPython and IronRuby projects. originally asp.net MVC was designed for IronPython. when it switched to C#, binding changed from expando objects to using reflection, attributes and expression trees (for intellisense support).

    you can bind to Dictionary<string,string> which will allows dynamic forms. You will need additional datatype meta data, and will need to create you own validation, but you probably wanted this anyway for the dynamic forms.

    0 comments No comments

  2. Zhi Lv - MSFT 32,006 Reputation points Microsoft Vendor
    2022-09-20T02:34:45.827+00:00

    Hi @Oscar Lauroba ,

    in Blazor hybrid apps and it seems it's not possible binding html inputs to expando object's properties.

    This is a known issue, and it is not a feature that asp.net Blazor currently support. The Blazor form elements require a statically typed model to work. So we can't directly bind the ExpandoObject. You can submit this feedback about this issue on the Github.

    As a workaround, you can use a Dictionary to store the relates value and assign to the ExpandoObject, then in the form, convert the ExpandoObject to the IDictionary and loop the items to display the value. Refer to the following sample (view the source code):

    242690-image.png

    The result as below(this is a Blazor MAUI application):

    242753-1.gif


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Dillion

    0 comments No comments

  3. Oscar Lauroba 1 Reputation point
    2022-09-21T08:58:21.143+00:00

    Hi Dillion, thank you very much.
    Currently it seems it's the way to go, but I can't achieve data binding a property that's not a string, for example DateTime.243409-sourcecode-2022-09-21.txt
    Please, see the atached file.

    @page "/counter"  
       
    @using System.Dynamic  
      
    <h1>Counter</h1>   
    <button class="btn btn-primary" @onclick="CheckValue">Check ExpandoObject Value</button>  
      
    <div class="mb-3">  
       <label class="form-label">Date</label>  
       <input type="date" class="form-control" value=@(product["date"]) />  
       <input type="text" class="form-control" value=@(product["date"]) />  
    </div>  
      
    @foreach (var option in (IDictionary<string, object>)selectedProduct.Properties)  
    {  
        <div class="col-sm">  
            <input type="text" placeholder="@option.Key" value="@option.Value"  
            @onchange="@((ChangeEventArgs __e) => ((IDictionary<string, object>)selectedProduct.Properties)[option.Key] = (object)__e.Value.ToString())"/>  
        </div>  
    }  
      
    @code {   
      
        private dynamic selectedProduct = new ExpandoObject();  
          
        private IDictionary<string, object> product;  
        private dynamic expnProduct = new ExpandoObject();  
          
        protected override async Task OnInitializedAsync()  
        {  
            Dictionary<string, object> properties = new Dictionary<string, object>();  
            properties.Add("color", "red");  
            properties.Add("size", "100*100");  
            properties.Add("weight", "10kg");  
      
            selectedProduct.Properties = properties;   
      
            product = (IDictionary <String, Object>) expnProduct;  
            product["color"] = "red";  
            product["size"] = 100;  
            product["weight"] = 10.50D;  
            expnProduct.name = "Product One"; // product["name"] = "Product one"  
            expnProduct.date = DateTime.Today;  
        }  
      
        private void CheckValue()  
        {  
            var data = selectedProduct;  
        }   
    }