Passing collection name dynamically - asp.net

Can any one suggest for a simple but tricky query. I have a function like
public object GetPropertyValue(object obj_, string property_)
{
return HttpContext.Current.Request.Headers[property_];
}
But I want to use Obj_ instead of hard coding the headers in return value. Because it can be Headers/ cookies/...or anything
Something like HttpContext.Current.Request.obj_[property_];
Please anyone???

You can use
HTTPContext.Current.Request[YOUR_PROPERTY_NAME] ;
it has an indexer which reads from the QueryString, Form, Cookies, or ServerVariables collections.
http://msdn.microsoft.com/en-gb/library/system.web.httprequest.item.aspx

Related

Delete WebApi FromURI binding

I am trying to create a .NET5 WebApi delete method in a controller class where this method receives several "ids" that will be used for deleting some entities.
I realized when building the delete request on the client side that specifying a content does not make sense. So I was guided to pass ids on the Uri, hence the use of the "FromUri" attribute:
// DELETE: api/ProductionOrders/5
[HttpDelete("ProductionOrders")]
public IActionResult DeleteProductionOrder([System.Web.Http.FromUri]int[] ids)
{
//code
}
If this is a reasonable approach, is there a better way to build this Uri from the client-side? Imagine instead of an array of ints I had a complex type. How can I serialized this and put into the Uri?
For this example I end up building up a URI like this:
http://localhost:51081/api/ProductionOrders?ids=25563&ids=25533
Personally, if I have to pass a List or a complex type I would map values from the Body via JSON. The DELETE allow using body. And then just decorate your param with [FromBody] attribute.
Despite some recommendations not to use the message body for DELETE requests, this approach may be appropriate in certain use cases.
This allows better extensibility in case you need to change how the data is coming.
In your case with ids I’d create new class like this:
public class RequestEntity {
[JsonPropertyName("Ids")]
public List<int> Ids { get; set; }
}
And then when calling this method, send the Body along with the request.
{
"Ids": [25392, 254839, 25563]
}
In a future you can pass complex objects just by changing what is send to server and implement complex logic.

ZF2: Prefill fieldset data

I've got an issue with my fieldset in Zend Framework 2.
The user is able to save his personal data over a form. If he already save this, they should be prefilled with the data from database. This worked fine as it was only a form, but I need the address data in a fieldset, so that I can use it at other parts of my program. Now the input fields stays empty.
At the beginning, I fill the personal data in a session. My data looks like this:
object(Application\Model\Product\PersonalData)#247 (3) {
["tel":protected]=> string(0) ""
["birthday":protected]=> string(10) "2013-01-01"
["address":protected]=> object(Application\Model\Account\Addresses)#248 (15) {
["firstname":protected]=> string(5) "Ernie"
["surname":protected]=> string(6) "Muppet"
...
}
}
As you can see, the data is already bind to the given objects, PersonalData as main, and Addresses for the fieldset. This seems to work then.
Then I put it in my form:
$oForm->setData($oForm->getHydrator()->extract($_SESSION->getPersonalData()));
return new ViewModel(array('form'=>$oForm));
The addressFieldset has a hydrator and a binding, which does work, because all objects are perfectly filled. The only problem is, that when I open the page, the input-fields are empty, only birthday and telephone are filled, which are directly on the form
My form implements the address-fieldset like this:
$addressFieldset = new AddressFieldset($lang);
$addressFieldset->setUseAsBaseFieldset(true);
$addressFieldset->setName('address');
$this->add($addressFieldset);
I think that it might be just a problem with the correct addressing of my fieldset, but I can't explain why it would be filled correctly after posting the data then. All I want is that he fill the setData in my Fieldset.
I hope you understand my question and could help me.
Thanks a lot,
Svenja
EDIT:
I analysed it a bit more now, it's very strange and I don't know what went wrong.
When I debug I can see that $fieldset->getValue() returns all data I need. So I thought that the binding might be wrong and I did this to debug it step by step:
$values = $this->form->get('address')->getValue();
$addressFieldset = $this->form->get('address');
$aValues = $addressFieldset->getHydrator()->extract($values);
$addressFieldset->bindValues($aValues);
I went to the Fieldset.php and bindValues does perfectly what it should (it is only a recapitulation anyway(?)), call the hydrator and fill my object. But if I show in the elements, all values are NULL.
I already checked my elements twice. The only different between the model and the elements is a different order of declaration. I call the method setUseAsBaseField(true) in the fieldset and the form, too. I can't understand why the data is in values but not in elements.
It's very strange, because I have something and it good work. Are you confident that the expression $_SESSION->getPersonalData() to return the desired result? You are using a very strange session.
http://framework.zend.com/manual/2.1/en/modules/zend.session.container.html
To EDIT (I'm sorry my english):
You can use different types of hydrator, for example
ArraySerializable (by default, your entity must have getArrayCopy()
and exchangeArray() methods, in your case) ArraySerializable is the hydrator by default.
First you have to bind a form with entity $form->bind(new Entity()); The entity will bind to the base fieldset. If the base fieldset not specified, the entity will bind with the form, because the form inherits fieldset. If the entity is an aggregate, ie, its properties contain another objects, for each of these objects should be your fildset.
In constructor this children fieldsets you should use
$this->setObject(new MyChildrenEntity());
As a result, the entity properties will be extracted to the form
elements.
After that, you should only work with the form, but not with its
elements or fieldsets.
You can pass any data in the form, so form elements will get this
values. $form->setData($this->getRequest()->getPost()); This method use internal populateValues() method. If the form has elements with an appropriate name, they will be assigned to these values​​. If the form has fieldsets, they will also be transferred to these values​​.
As long as the form fails to validate, the entity of these values
​​will not be assigned. These values ​​are assigned to entities only
in case of successful verification. IsValid () method uses the
internal method bindValues ​​() if the validation was successful.
After successful validation, you can get the entity using getData()
method $entity = $form->getData();
P.S.: If you are doing a complex "haсk", do not be offended by this simple explanation.
I finally found the solution!
At first, this link helped me:
Populating fieldsets
I didn't integrate the fieldset Input-Filter in the Form Input Filter.
But that wasn't all I have to do. My Form-Datamodel looks like this:
interface IPersonalData
{
public function getTel();
public function getBirthday();
public function getAddress();
public function setTel($tel);
public function setAddress(IAddresses $address);
public function setBirthday($birthday);
}
This is only the interface, but Address is an object. And that is the problem. When the form tries to fill the fieldset, he only accept arrays. So I have to extract my object in the getter-method to an array.
I don't think that this is very useful, because I normaly want to get my object with this method. So I write a method "getAddressAsArray()" which looks like this:
public function getAddressAsArray()
{
$oAddressHydrator = new AddressHydrator();
if(isset($this->address))
{
return $oAddressHydrator->extract($this->address);
}
return array();
}
The extract-method of my hydrator changed like this:
public function extract($object)
{
if(!$object instanceof IPersonalData)
{
throw new \InvalidArgumentException('$object must be an instance of Application\Model\Product\IPersonalData');
}
return array(
'telephone' => $object->getTel(),
'address' => $object->getAddressAsArray(),
'birthday' => $object->getBirthday(),
);
}

MVC RedirectToAction() any way to pass object to the target action?

The populated catList is always Count=0 when the code jumps to CreateProduct() so I take it it does not get delivered.
Considering RouteValueDictionary does not do this ? Any other way?
public ActionResult GetCats(int CatID)
{
List<Category> catList = new List<Category>();
if (CatID >= 0 )
{
catList = context.Categories.Where(x => x.PCATID == CatID).ToList();
}
return RedirectToAction("CreateProduct", "Admin", new { catList });
}
public ActionResult CreateProduct(List<Category> catList) { }
You are actually trying to use controllers to do data access.
Move the "GetCats" data retrieval into your business layer (Service object, Repository, whatever suits you).
Then, CreateProduct will need to be there twice (2 signatures). One with no parameters in which you are going to call "GetCats" from your business layer and send it to the view.
The other implementation is going to be the flagged with the HttpPostAttribute and will contain in parameters all the necessary information to create a cat.
That's all. Simple and easy.
You could place any items that you need in TempData then call RedirectToAction.
RedirectToAction simply returns a "302" code to the browser with the URL to redirect to. When this happens your browser performs a GET with that URL.
Your RouteValues need to be simple. You can't really pass complex object or collections using a route value.
if you don't care about the browser url changing you could just
return CreateProduct(catList)

ASP.NET MVC Model List in controller

I'm using ajax and trying to pass the Model back, which is a generic List < T >. I tried Model.ToList() but I don't think I'm going about this correctly. I think it is already setup but I just need to find the method or property name to get the List that was posted, which might not work since my Model from the controller contains a couple of lists to pass to different partials and one of these partials, I'm trying to update the partial view. I'm basically trying to sort the list. So using an AJAX to call the controller but I need the list to sort and call the partial again. I hope my explanation wasn't too confusing.
If these are just single values you are passing back, such as int, strings, floats, etc. You can just put the array in the action like so:
public ActionResult MyAction (int id, string[] value)
Or you can use something called a FormCollection
public ActionResult MyAction (int id, FormCollection form) {
string[] values = form.GetValues("value");
Or you can use Request.Form (this is not recommended, because the above two are more recommended
public ActionResult MyAction(int id) {
string[] values = Request.Form.GetValues("value");
Hope this helps. I didn't totally understand what your question was, but it seemed to be dealing with how to get an array of posted values.

modifying a value in viewstate

Say I have a property like...
public object MyObject
{
get { return (object)ViewState["myobject"]; }
set { ViewState["myobject"] = value; }
}
I modify the object like so...
object myObjCopy = MyObject;
myObjCopy.ChangeSomething();
MyObject = myObjCopy;
Is this the correct method? It just feels really clunky and I wonder if I'm missing something. Is there some clever paradigm which enables modifying viewstate more intuitively without using temporary copys everywhere in my code.
With the property you have defined, you should not need to do any copying like what you have. I'm not sure what ChangeSomething() does, but you should be able to call it directly on the property. I would normally not pull it out as an object... It's been a while since I did pure webforms development, but my ViewState helper properties usually looked more like:
public string CurrentUsername
{
get
{
if (ViewState["Username"] is string)
return (string)ViewState["Username"];
return null;
}
set { ViewState["Username"] = value; }
}
Edit: Thinking about it, I guess the copy is probably there just to remove the potential performance overhead of casting every time you reference the property. I don't think this is a valid optimization in most cases, but if you feel strongly about it, you could hide it with something like this:
private string m_CurrentUsername;
public string CurrentUsername
{
get
{
if (m_CurrentUsername == null && ViewState["Username"] is string)
m_CurrentUsername = (string)ViewState["Username"];
return m_CurrentUsername;
}
set { ViewState["Username"] = m_CurrentUsername = value; }
}
Like I said though - I wouldn't recommend this.
The correct answer is that you shouldn't be modifying viewstate at all. Your controller should create the models and populate the viewstate only just before returning the view. If you're writing this code in the view, you've got an even bigger problem. in general, the view should contain little (if any) code that changes or does things.
Edit: Oops, I think I just got ViewData (in asp.net mvc) confused with viewdata. sorry ... to answer your real question, yes, that is just about the only way :-) it's not really clunky when you are dealing with a "bag" API like the viewstate is.

Resources