I have a master-detail application that consumes an OData service (declared in manifest.json).
In the detail controller, I bind the model to the view in the following way (this method is attached to a router object).
_onObjectMatched: function(oEvent) {
this.getView().bindElement({
path: "/ContractCompSet('" + oEvent.getParameter("arguments").id + "')",
model: "contracts"
});
}
How can I access the actual bound model object from within this controller?
Closest I got (but seems too be a little too complicated) is as follows
var path = this.getView().getElementBinding('contracts').sPath.substring(1);
var model = this.getView().getModel('contracts').oData[path];
Well your approach isn't to far off and is indeed pretty much the same as hirses.
The point is the binding does not contain "just" the bound model object. It contains the information about model, path to the "bound object" and context. These can be retrieved from the binding. To access the "bound object" you then have basically two paths available.
Get the model and path from the binding and access the "bound object" via the model: (this is what you and hirse outlined)
var path = this.getView().getElementBinding('contracts').sPath;
var boundObject = this.getView().getModel('contracts').getProperty(path);
Or get the context and path and access the "bound object" that way:
var context = this.getView().getElementBinding('contracts').oContext;
var boundObject = context.getProperty(context.getPath());
Without having done to much research into this I would prefer the second option. It just seems more along the line of how the context binding is intended.
I would have thought,
this.getView().getModel('contracts')
gives you the Model Object (as in an object of type sap.ui.model.Model or subclass).
If you are referring to the data in the Model, you can use the following:
this.getView().getModel('contracts').getProperty("/")
Related
I have a method with this signature
public IEnumerable<T> GetAll<T>() where T : new()
{
// Orm Lite Version
return Connection.LoadSelect<T>();
}
At compile time I don't know the Type T. I only know the class name at runtime is it possible to call this method using reflection with something like this?
string TargetTBLName = ...;//TargetTBLName get's it's value at runtime
Type ParentTableClass = Type.GetType(TargetTBLName);
IEnumerable<Type.GetType(TargetTBLName)> test = Repository.GetAll<Type.GetType(TargetTBLName)>();
Any Ideas?
I'd give a Dynamitey library a go. You can do that in many different ways, but I prefer this one because of its simplicity. You can find it here.
var name = InvokeMemberName.Create;
var test = Dynamic.InvokeMember(Repository, name("GetAll", new[]{ParentTableClass }));
foreach(var obj in test)
{
obj.SomeMethodFromMyType();
}
Keep in mind, that if Repository is static, than you have to tweak it a bit to use static invocation context (look up the link).
Now you have a test object, which is a dynamic - you can use it with duck typing (which has some implications on speed, for example), but in general you can do whatever you want to do with a normal IEnumerable<YourType>.
If you want to use reflection:
MethodInfo getAll= typeof(Repository).GetMethod("GetAll");
MethodInfo getAllGeneric= getAll.MakeGenericMethod(ParentTableClass);
object result = getAllGeneric.Invoke(this, null);
//or null, null is Repository is static
var finalObject = result as IEnumerable;
Mind that since this ParentTableClass is an unknown during compilation, you won't have access to anything that the actual type provides - unless you use dynamic approach.
I have defined odata route using MapODataServiceRoute in my WebApiConfig.
config.Routes.MapODataServiceRoute("CompanyoOdata", "odata", GetImplicitEdm(config));
private static IEdmModel GetImplicitEdm(HttpConfiguration config)
{
ODataModelBuilder builder = new ODataConventionModelBuilder(config, true);
builder.EntitySet<Company>("Company");
builder.EntitySet<Photo>("Photos");
builder.EntitySet<Country>("Country");
return builder.GetEdmModel();
}
The data service works just fine. But I want to achieve few things.
I don't want to expose my metadata or associations because i'm using it internally and will not need metadata. How can I restrict access to these information (i.e restrict access to http://www.sample.com/odata/#metadata or http://www.sample.com/odata/$metadata)
secondly, I want to ignore some properties from getting serialized. I found two ways of doing this.
Using data contracts and marking properties with [DataMember] attribute or [IgnoreDataMember] attribute
Using Ignore method on EntitySet when building the model
I can't use the first method as I'm using Database first approach for entity framework hence can't decorate the entity with attributes. I thought I can achieve this by using MetaDataType, but it seems it only works for DataAnnotations.
I used second method with success, but you can't pass more than one property in the ignore method. Has to do it to individual property that I need to ignore, which is a bit tedious. Is there another way to do this?
any help really appreciated.
If want to hide metadata (/$metadata) or service document (/), can remove the the MetadataRoutingConvention from existing routing conventions, e.g.:
var defaultConventions = ODataRoutingConventions.CreateDefault();
var conventions = defaultConventions.Except(
defaultConventions.OfType<MetadataRoutingConvention>());
var route = config.MapODataServiceRoute(
"odata",
"odata",
model,
pathHandler: new DefaultODataPathHandler(),
routingConventions: conventions);
If only expose a few properties per type, can use ODataModelBuilder instead of ODataConventionModelBuilder. E.g., some example:
ODataModelBuilder builder = new ODataModelBuilder();
EntityTypeConfiguration<Customer> customer = builder.EntitySet<Customer>("Customers").EntityType;
customer.HasKey(c => c.Id);
customer.Property(c => c.Name);
Here is my code:
public ModelAndView login(#ModelAttribute("testVO") TestVO testVO){
//test the VO work theory
//testVO = new TestVO();
testVO.setTestStr("this is my test!");
return "index/index";
}
When I used the new to create a object for the testVO.
I can not get the value in my jsp page.
If I used set method, it works.
So, I think:
The object testVo has been create by the IOC container, so the JSP get the reference from the container, not the one I create by my self.
Am I right?
Thanks in advanced.
You guessed it right. Below text is from spring docs:
An #ModelAttribute on a method argument indicates the argument should be
retrieved from the model. If not present in the model, the argument should be
instantiated first and then added to the model.
If you want to create it yourself, you explicity need to add it to the model (as below) so that can be used in your jsp
public String login(Model model){
TestVO testVO = new TestVO();
testVO.setTestStr("this is my test!");
model.addAttribute("testVO", testVO);
return "index/index";
}
Man, here is the best explanation of #ModelAttribute annotation:
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-methods
Read at least two chapters. This will give you a theoretical knowledge.
A practical side of question you can find on my blog:
http://fruzenshtein.com/spring-mvc-form-handling/
I hope it will be helpful for you
I am intending to pass a Hotel model to my Controller Action - Do some checks/processing on it, then return a potentially different Hotel model rendered in a Partial View.
The problem I'm getting is that if I pass the oHotelParameter Model to the Action then the PartialView uses the model passed to the Action instead of the one passed to the PartialView method.
If I remove the oHotelParameter Parameter from the Action then the View is Rendered as expected using oHotel.
public ActionResult _SaveMasterDetails(Hotel oHotelParameter)
{
//Do some processing on oHotelParameter
//........
Hotel oHotel = new Hotel();
oHotel.GetHotelInfoById(14); //This gets a different Hotel object just for a test
//For some reason oHotel is ignored and oHotelParameter is used instead unless I remove oHotelParameter
return PartialView("_MasterDetails", oHotel);
}
When I debug the View I see that the Model is set to the value I pass to PartialView (oHotel), yet the result I see coming back from the Action contains data from the oHotelParameter object.
In case it makes a difference, I am calling the Action from jQuery ajax.
Can anyone explain why this should happen?
when mvc handles a form post, it fills the ModelState object with the details of the model.
This is when used when the view is rendered again from the post action, this is incase you have thrown the view back out because it has failed validation.
If you want to pass out a new model and not use the view state, then you can call ModelState.Clear() before returning the view and that should let you rebind the view to the new model.
I think that it would help if you had a better understanding of how model binding works when you post back to an action method. In most cases, it is unecessary and inefficient to pass a view model as a parameter to a POST action method. What you are doing is loading the view model into memory twice when you pass your view model as a parameter (assuming a strongly typed view). When you do a post back the model becomes part of the form collection (through model binding) in the request object in the BaseController class that every controller inherits from. All that you need to do is to extract the model from the Form collection in the Request object in the BaseController. It just so happens that there is a handy method, TryUpdateModel to help you do this. Here is how you do it
[POST]
public ActionResult Save()
{
var saveVm = new SaveViewModel();
// TryUpdateModel automatically populates your ViewModel!
// TryUpdateModel also calls ModelState.IsValid and returns
// true if your model is valid (validation attributes etc.)
if (TryUpdateModel(saveVm)
{
// do some work
int id = 1;
var anotherSaveVm = GetSaveVmBySomeId(id);
// do more work with saveVm and anotherSaveVm
// clear the existing model
ModelState.Clear();
return View(anotherSaveVm);
}
// return origonal view model so that the user can correct their errors
return View(saveVm);
}
I think that the data in the form collection contained in the request object is being returned with the view. When you pass the model back to the post action method as a parameter, I believe it is passed in the query string (see Request.QueryString). Most of the time, it is best to only pass one or two primitive type parameters or primitive reverence types such as int? to an action method. There is no need to pass the entire model as it is already contained in the Form collection of the Request object. If you wish to examine the QueryString, seee Request.QueryString.
Or at least, they don't do what I was expecting. My Action method looks like this:
Function Test() As ActionResult
Dim model As Object = New ExpandoObject()
model.FieldA = 123
model.FieldB = "This is a string"
model.FieldC = DateTime.Now
Return View(model)
End Function
and the view looks like this:
#ModelType Object
#Html.DisplayForModel
I was expecting it to produce the same thing you'd get if the model were a real object with those fields, but instead I get this:
[FieldA, 123][FieldB, This is a string][FieldC, 3/29/2012 12:10:24 PM]
EditorForModel does the exact same thing. Is this the correct behavior, and what's the best way to implement the behavior that I'm looking for?
Yes, this is the correct behavior. Default metadata provider (DataAnnotationsModelMetadataProvider) uses reflection to get model information and that is the reason you get this result.
I would suggest to create a custom metadata provider that will work correctly with dynamics. Try to inherit from this class - http://msdn.microsoft.com/en-us/library/system.web.mvc.dataannotationsmodelmetadataprovider.aspx.