Quoc Nguyen
Quoc Nguyen

Reputation: 360

How can i pass an object (Entity) as a parameter on WebApi Odata

i follow this link Supporting OData Actions in ASP.NET Web API And i want to pass my object/Entity as a parameter like this:

ActionConfiguration addNewPatient = builder.Entity<Patient>().Collection.Action("AddNewPatient");
        addNewPatient.Parameter<int>("hospId");
        addNewPatient.Parameter<int>("docId");
        addNewPatient.Parameter<Patient>("patient");
        addNewPatient.Returns<bool>();

but i got this issue:

System.ArgumentException: Invalid parameter type 'Patient'. 
A non-binding parameter type must be either Primitive, Complex, Collection of Primitive or a Collection of Complex.
Parameter name: parameterType

I tried to implement this

   ActionConfiguration addNewPatient = builder.Entity<Patient>().Collection.Action("AddNewPatient");
    addNewPatient.Parameter<int>("hospId");
    addNewPatient.Parameter<int>("docId");
    var patientConfig = builder.StructuralTypes.OfType<EntityTypeConfiguration>().Single(x => x.Name == "Patient");
    addNewPatient.SetBindingParameter("patient", patientConfig, false);
    addNewPatient.Returns<bool>();

but i can't call method POST ../odata/Patient/AddNewPatient anymore

<FunctionImport Name="AddNewPatient" ReturnType="Edm.Boolean"      IsBindable="true">
<Parameter Name="patient" Type="Patient"/>
<Parameter Name="hospId" Type="Edm.Int32" Nullable="false"/>
<Parameter Name="docId" Type="Edm.Int32" Nullable="false"/>
</FunctionImport>

Please help me, i tried various way but still no luck. Thanks.

Upvotes: 4

Views: 5882

Answers (2)

Alex
Alex

Reputation: 297

You can use the ActionConfiguration.EntityParameter() method to bind an entity as a parameter to your OData action method.

Here is an example:

ActionConfiguration validate = ModelBuilder.EntityType<TEntity>()
    .Collection.Action("Validate");
validate.Namespace = "Importation";
validate.EntityParameter<TEntity>(typeof(TEntity).Name);
validate.CollectionParameter<string>("UniqueFields");
validate.Returns<ValidationResult>();

However, note that the ModelState will not check against the content of the supplied Entity and will set any missing properties to null and properties exceeding the StringLength(x) annotation in your model will still pass. If you wish to validate the entity itself after, use this bit of code in your action method:

[HttpPost]
public virtual IHttpActionResult Validate(ODataActionParameters parameters)
{
//First we check if the parameters are correct for the entire action method
    if (!ModelState.IsValid)
    {
         return BadRequest(ModelState);
    }
    else
    {
         //Then we cast our entity parameter in our entity object and validate
         //it through the controller's Validate<TEntity> method
         TEntity Entity = (TEntity)parameters[typeof(TEntity).Name];
         Validate(Entity, typeof(TEntity).Name);
         if (!ModelState.IsValid)
         {
              return BadRequest(ModelState);
         }
         IEnumerable<string> uniqueFields = parameters["UniqueFields"] as IEnumerable<string>;
         bool result = Importer.Validate(Entity, uniqueFields);
         return Ok(result);
    }
}

Upvotes: 3

Andy Irving
Andy Irving

Reputation: 2697

Would it not be better to just POST to /odata/Patient your new patient object? that's kind of what it's there for.

If you want to do it the way you've described, you need to create an intermediate type, and make the parameter of that type, then convert between that and your Edm type.

var createPatient = modelBuilder.Entity<Patient>().Collection.Action("AddNewPatient");
createPatient.CollectionParameter<PatientPdo>("patient");

where PatientPdo is exactly the same as Patient, just with the navigation properties removed. That's what it's complaining about, that it's Edm types all the way down, so to speak.

public class PatientPdo
    {
        public long Id{ get; set; }

        public Entity ToEdmEntity()
        {
            return new Patient
                {
                    Id= Id
                };
        }
    }

Upvotes: 0

Related Questions