如何将对象(实体)作为WebApi Odata的参数传递

时间:2022-08-22 15:14:11

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:

我遵循这个链接来支持ASP中的OData操作。NET Web API,我想将我的对象/实体作为如下参数传递:

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

但是我不能调用方法POST。odata /耐心/ AddNewPatient了

<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.

请帮帮我,我尝试了各种方法但还是没有成功。谢谢。

2 个解决方案

#1


3  

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

您可以使用ActionConfiguration.EntityParameter()方法将实体作为参数绑定到您的OData操作方法。

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:

但是,请注意,ModelState将不会检查提供的实体的内容,并将任何丢失的属性设置为null,超过模型中的StringLength(x)注释的属性仍将通过。如果您希望在之后验证实体本身,请在您的操作方法中使用这段代码:

[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);
    }
}

#2


0  

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

仅仅将您的新病人对象发布到/odata/Patient不是更好吗?这就是它的目的。

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.

如果您想按照您所描述的方式进行,您需要创建一个中间类型,并创建该类型的参数,然后在该类型和您的Edm类型之间进行转换。

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.

PatientPdo与Patient是完全相同的,只是去掉了导航属性。这就是它所抱怨的,可以说,它的Edm类型一直在下降。

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

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

#1


3  

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

您可以使用ActionConfiguration.EntityParameter()方法将实体作为参数绑定到您的OData操作方法。

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:

但是,请注意,ModelState将不会检查提供的实体的内容,并将任何丢失的属性设置为null,超过模型中的StringLength(x)注释的属性仍将通过。如果您希望在之后验证实体本身,请在您的操作方法中使用这段代码:

[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);
    }
}

#2


0  

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

仅仅将您的新病人对象发布到/odata/Patient不是更好吗?这就是它的目的。

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.

如果您想按照您所描述的方式进行,您需要创建一个中间类型,并创建该类型的参数,然后在该类型和您的Edm类型之间进行转换。

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.

PatientPdo与Patient是完全相同的,只是去掉了导航属性。这就是它所抱怨的,可以说,它的Edm类型一直在下降。

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

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